summaryrefslogtreecommitdiff
path: root/lib/Class
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Class')
-rw-r--r--lib/Class/MOP.pm1232
-rw-r--r--lib/Class/MOP/Attribute.pm1100
-rw-r--r--lib/Class/MOP/Class.pm2312
-rw-r--r--lib/Class/MOP/Class/Immutable/Trait.pm172
-rw-r--r--lib/Class/MOP/Deprecated.pm95
-rw-r--r--lib/Class/MOP/Instance.pm533
-rw-r--r--lib/Class/MOP/Method.pm343
-rw-r--r--lib/Class/MOP/Method/Accessor.pm409
-rw-r--r--lib/Class/MOP/Method/Constructor.pm251
-rw-r--r--lib/Class/MOP/Method/Generated.pm142
-rw-r--r--lib/Class/MOP/Method/Inlined.pm195
-rw-r--r--lib/Class/MOP/Method/Meta.pm169
-rw-r--r--lib/Class/MOP/Method/Wrapped.pm331
-rw-r--r--lib/Class/MOP/MiniTrait.pm113
-rw-r--r--lib/Class/MOP/Mixin.pm111
-rw-r--r--lib/Class/MOP/Mixin/AttributeCore.pm125
-rw-r--r--lib/Class/MOP/Mixin/HasAttributes.pm171
-rw-r--r--lib/Class/MOP/Mixin/HasMethods.pm304
-rw-r--r--lib/Class/MOP/Mixin/HasOverloads.pm237
-rw-r--r--lib/Class/MOP/Module.pm213
-rw-r--r--lib/Class/MOP/Object.pm200
-rw-r--r--lib/Class/MOP/Overload.pm342
-rw-r--r--lib/Class/MOP/Package.pm464
23 files changed, 9564 insertions, 0 deletions
diff --git a/lib/Class/MOP.pm b/lib/Class/MOP.pm
new file mode 100644
index 0000000..e55527d
--- /dev/null
+++ b/lib/Class/MOP.pm
@@ -0,0 +1,1232 @@
+package Class::MOP;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use 5.008003;
+
+use MRO::Compat;
+use Class::Load 0.07 ();
+use Scalar::Util 'weaken', 'isweak', 'blessed';
+use Data::OptList;
+
+use Class::MOP::Mixin::AttributeCore;
+use Class::MOP::Mixin::HasAttributes;
+use Class::MOP::Mixin::HasMethods;
+use Class::MOP::Mixin::HasOverloads;
+use Class::MOP::Class;
+use Class::MOP::Attribute;
+use Class::MOP::Method;
+
+BEGIN {
+ *IS_RUNNING_ON_5_10 = ($] < 5.009_005)
+ ? sub () { 0 }
+ : sub () { 1 };
+
+ # this is either part of core or set up appropriately by MRO::Compat
+ *check_package_cache_flag = \&mro::get_pkg_gen;
+}
+
+XSLoader::load(
+ 'Moose',
+ $VERSION,
+);
+
+{
+ # Metaclasses are singletons, so we cache them here.
+ # there is no need to worry about destruction though
+ # because they should die only when the program dies.
+ # After all, do package definitions even get reaped?
+ # Anonymous classes manage their own destruction.
+ my %METAS;
+
+ sub get_all_metaclasses { %METAS }
+ sub get_all_metaclass_instances { values %METAS }
+ sub get_all_metaclass_names { keys %METAS }
+ sub get_metaclass_by_name { $METAS{$_[0]} }
+ sub store_metaclass_by_name { $METAS{$_[0]} = $_[1] }
+ sub weaken_metaclass { weaken($METAS{$_[0]}) }
+ sub metaclass_is_weak { isweak($METAS{$_[0]}) }
+ sub does_metaclass_exist { exists $METAS{$_[0]} && defined $METAS{$_[0]} }
+ sub remove_metaclass_by_name { delete $METAS{$_[0]}; return }
+
+ # This handles instances as well as class names
+ sub class_of {
+ return unless defined $_[0];
+ my $class = blessed($_[0]) || $_[0];
+ return $METAS{$class};
+ }
+
+ # NOTE:
+ # We only cache metaclasses, meaning instances of
+ # Class::MOP::Class. We do not cache instance of
+ # Class::MOP::Package or Class::MOP::Module. Mostly
+ # because I don't yet see a good reason to do so.
+}
+
+sub load_class {
+ Class::MOP::Deprecated::deprecated(
+ message => 'Class::MOP::load_class is deprecated',
+ feature => 'Class::Load wrapper functions',
+ );
+ require Class::Load;
+ goto &Class::Load::load_class;
+}
+
+sub load_first_existing_class {
+ Class::MOP::Deprecated::deprecated(
+ message => 'Class::MOP::load_first_existing_class is deprecated',
+ feature => 'Class::Load wrapper functions',
+ );
+ require Class::Load;
+ goto &Class::Load::load_first_existing_class;
+}
+
+sub is_class_loaded {
+ Class::MOP::Deprecated::deprecated(
+ message => 'Class::MOP::is_class_loaded is deprecated',
+ feature => 'Class::Load wrapper functions',
+ );
+ require Class::Load;
+ goto &Class::Load::is_class_loaded;
+}
+
+sub _definition_context {
+ my %context;
+ @context{qw(package file line)} = caller(1);
+
+ return (
+ definition_context => \%context,
+ );
+}
+
+## ----------------------------------------------------------------------------
+## Setting up our environment ...
+## ----------------------------------------------------------------------------
+## Class::MOP needs to have a few things in the global perl environment so
+## that it can operate effectively. Those things are done here.
+## ----------------------------------------------------------------------------
+
+# ... nothing yet actually ;)
+
+## ----------------------------------------------------------------------------
+## Bootstrapping
+## ----------------------------------------------------------------------------
+## The code below here is to bootstrap our MOP with itself. This is also
+## sometimes called "tying the knot". By doing this, we make it much easier
+## to extend the MOP through subclassing and such since now you can use the
+## MOP itself to extend itself.
+##
+## Yes, I know, that's weird and insane, but it's a good thing, trust me :)
+## ----------------------------------------------------------------------------
+
+# We need to add in the meta-attributes here so that
+# any subclass of Class::MOP::* will be able to
+# inherit them using _construct_instance
+
+## --------------------------------------------------------
+## Class::MOP::Mixin::HasMethods
+
+Class::MOP::Mixin::HasMethods->meta->add_attribute(
+ Class::MOP::Attribute->new('_methods' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ '_method_map' => \&Class::MOP::Mixin::HasMethods::_method_map
+ },
+ default => sub { {} },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::HasMethods->meta->add_attribute(
+ Class::MOP::Attribute->new('method_metaclass' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'method_metaclass' => \&Class::MOP::Mixin::HasMethods::method_metaclass
+ },
+ default => 'Class::MOP::Method',
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::HasMethods->meta->add_attribute(
+ Class::MOP::Attribute->new('wrapped_method_metaclass' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'wrapped_method_metaclass' => \&Class::MOP::Mixin::HasMethods::wrapped_method_metaclass
+ },
+ default => 'Class::MOP::Method::Wrapped',
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Mixin::HasAttributes
+
+Class::MOP::Mixin::HasAttributes->meta->add_attribute(
+ Class::MOP::Attribute->new('attributes' => (
+ reader => {
+ # NOTE: we need to do this in order
+ # for the instance meta-object to
+ # not fall into meta-circular death
+ #
+ # we just alias the original method
+ # rather than re-produce it here
+ '_attribute_map' => \&Class::MOP::Mixin::HasAttributes::_attribute_map
+ },
+ default => sub { {} },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::HasAttributes->meta->add_attribute(
+ Class::MOP::Attribute->new('attribute_metaclass' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'attribute_metaclass' => \&Class::MOP::Mixin::HasAttributes::attribute_metaclass
+ },
+ default => 'Class::MOP::Attribute',
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Mixin::HasOverloads
+
+Class::MOP::Mixin::HasOverloads->meta->add_attribute(
+ Class::MOP::Attribute->new('_overload_map' => (
+ reader => {
+ '_overload_map' => \&Class::MOP::Mixin::HasOverloads::_overload_map
+ },
+ clearer => '_clear_overload_map',
+ default => sub { {} },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Package
+
+Class::MOP::Package->meta->add_attribute(
+ Class::MOP::Attribute->new('package' => (
+ reader => {
+ # NOTE: we need to do this in order
+ # for the instance meta-object to
+ # not fall into meta-circular death
+ #
+ # we just alias the original method
+ # rather than re-produce it here
+ 'name' => \&Class::MOP::Package::name
+ },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Package->meta->add_attribute(
+ Class::MOP::Attribute->new('namespace' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'namespace' => \&Class::MOP::Package::namespace
+ },
+ init_arg => undef,
+ default => sub { \undef },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Module
+
+# NOTE:
+# yeah this is kind of stretching things a bit,
+# but truthfully the version should be an attribute
+# of the Module, the weirdness comes from having to
+# stick to Perl 5 convention and store it in the
+# $VERSION package variable. Basically if you just
+# squint at it, it will look how you want it to look.
+# Either as a package variable, or as a attribute of
+# the metaclass, isn't abstraction great :)
+
+Class::MOP::Module->meta->add_attribute(
+ Class::MOP::Attribute->new('version' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'version' => \&Class::MOP::Module::version
+ },
+ init_arg => undef,
+ default => sub { \undef },
+ _definition_context(),
+ ))
+);
+
+# NOTE:
+# By following the same conventions as version here,
+# we are opening up the possibility that people can
+# use the $AUTHORITY in non-Class::MOP modules as
+# well.
+
+Class::MOP::Module->meta->add_attribute(
+ Class::MOP::Attribute->new('authority' => (
+ reader => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'authority' => \&Class::MOP::Module::authority
+ },
+ init_arg => undef,
+ default => sub { \undef },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Class
+
+Class::MOP::Class->meta->add_attribute(
+ Class::MOP::Attribute->new('superclasses' => (
+ accessor => {
+ # NOTE:
+ # we just alias the original method
+ # rather than re-produce it here
+ 'superclasses' => \&Class::MOP::Class::superclasses
+ },
+ init_arg => undef,
+ default => sub { \undef },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Class->meta->add_attribute(
+ Class::MOP::Attribute->new('instance_metaclass' => (
+ reader => {
+ # NOTE: we need to do this in order
+ # for the instance meta-object to
+ # not fall into meta-circular death
+ #
+ # we just alias the original method
+ # rather than re-produce it here
+ 'instance_metaclass' => \&Class::MOP::Class::instance_metaclass
+ },
+ default => 'Class::MOP::Instance',
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Class->meta->add_attribute(
+ Class::MOP::Attribute->new('immutable_trait' => (
+ reader => {
+ 'immutable_trait' => \&Class::MOP::Class::immutable_trait
+ },
+ default => "Class::MOP::Class::Immutable::Trait",
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Class->meta->add_attribute(
+ Class::MOP::Attribute->new('constructor_name' => (
+ reader => {
+ 'constructor_name' => \&Class::MOP::Class::constructor_name,
+ },
+ default => "new",
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Class->meta->add_attribute(
+ Class::MOP::Attribute->new('constructor_class' => (
+ reader => {
+ 'constructor_class' => \&Class::MOP::Class::constructor_class,
+ },
+ default => "Class::MOP::Method::Constructor",
+ _definition_context(),
+ ))
+);
+
+
+Class::MOP::Class->meta->add_attribute(
+ Class::MOP::Attribute->new('destructor_class' => (
+ reader => {
+ 'destructor_class' => \&Class::MOP::Class::destructor_class,
+ },
+ _definition_context(),
+ ))
+);
+
+# NOTE:
+# we don't actually need to tie the knot with
+# Class::MOP::Class here, it is actually handled
+# within Class::MOP::Class itself in the
+# _construct_class_instance method.
+
+## --------------------------------------------------------
+## Class::MOP::Mixin::AttributeCore
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('name' => (
+ reader => {
+ # NOTE: we need to do this in order
+ # for the instance meta-object to
+ # not fall into meta-circular death
+ #
+ # we just alias the original method
+ # rather than re-produce it here
+ 'name' => \&Class::MOP::Mixin::AttributeCore::name
+ },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('accessor' => (
+ reader => { 'accessor' => \&Class::MOP::Mixin::AttributeCore::accessor },
+ predicate => { 'has_accessor' => \&Class::MOP::Mixin::AttributeCore::has_accessor },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('reader' => (
+ reader => { 'reader' => \&Class::MOP::Mixin::AttributeCore::reader },
+ predicate => { 'has_reader' => \&Class::MOP::Mixin::AttributeCore::has_reader },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('initializer' => (
+ reader => { 'initializer' => \&Class::MOP::Mixin::AttributeCore::initializer },
+ predicate => { 'has_initializer' => \&Class::MOP::Mixin::AttributeCore::has_initializer },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('definition_context' => (
+ reader => { 'definition_context' => \&Class::MOP::Mixin::AttributeCore::definition_context },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('writer' => (
+ reader => { 'writer' => \&Class::MOP::Mixin::AttributeCore::writer },
+ predicate => { 'has_writer' => \&Class::MOP::Mixin::AttributeCore::has_writer },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('predicate' => (
+ reader => { 'predicate' => \&Class::MOP::Mixin::AttributeCore::predicate },
+ predicate => { 'has_predicate' => \&Class::MOP::Mixin::AttributeCore::has_predicate },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('clearer' => (
+ reader => { 'clearer' => \&Class::MOP::Mixin::AttributeCore::clearer },
+ predicate => { 'has_clearer' => \&Class::MOP::Mixin::AttributeCore::has_clearer },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('builder' => (
+ reader => { 'builder' => \&Class::MOP::Mixin::AttributeCore::builder },
+ predicate => { 'has_builder' => \&Class::MOP::Mixin::AttributeCore::has_builder },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('init_arg' => (
+ reader => { 'init_arg' => \&Class::MOP::Mixin::AttributeCore::init_arg },
+ predicate => { 'has_init_arg' => \&Class::MOP::Mixin::AttributeCore::has_init_arg },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('default' => (
+ # default has a custom 'reader' method ...
+ predicate => { 'has_default' => \&Class::MOP::Mixin::AttributeCore::has_default },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Mixin::AttributeCore->meta->add_attribute(
+ Class::MOP::Attribute->new('insertion_order' => (
+ reader => { 'insertion_order' => \&Class::MOP::Mixin::AttributeCore::insertion_order },
+ writer => { '_set_insertion_order' => \&Class::MOP::Mixin::AttributeCore::_set_insertion_order },
+ predicate => { 'has_insertion_order' => \&Class::MOP::Mixin::AttributeCore::has_insertion_order },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Attribute
+Class::MOP::Attribute->meta->add_attribute(
+ Class::MOP::Attribute->new('associated_class' => (
+ reader => {
+ # NOTE: we need to do this in order
+ # for the instance meta-object to
+ # not fall into meta-circular death
+ #
+ # we just alias the original method
+ # rather than re-produce it here
+ 'associated_class' => \&Class::MOP::Attribute::associated_class
+ },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Attribute->meta->add_attribute(
+ Class::MOP::Attribute->new('associated_methods' => (
+ reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
+ default => sub { [] },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Attribute->meta->add_method('clone' => sub {
+ my $self = shift;
+ $self->meta->clone_object($self, @_);
+});
+
+## --------------------------------------------------------
+## Class::MOP::Method
+Class::MOP::Method->meta->add_attribute(
+ Class::MOP::Attribute->new('body' => (
+ reader => { 'body' => \&Class::MOP::Method::body },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method->meta->add_attribute(
+ Class::MOP::Attribute->new('associated_metaclass' => (
+ reader => { 'associated_metaclass' => \&Class::MOP::Method::associated_metaclass },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method->meta->add_attribute(
+ Class::MOP::Attribute->new('package_name' => (
+ reader => { 'package_name' => \&Class::MOP::Method::package_name },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method->meta->add_attribute(
+ Class::MOP::Attribute->new('name' => (
+ reader => { 'name' => \&Class::MOP::Method::name },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method->meta->add_attribute(
+ Class::MOP::Attribute->new('original_method' => (
+ reader => { 'original_method' => \&Class::MOP::Method::original_method },
+ writer => { '_set_original_method' => \&Class::MOP::Method::_set_original_method },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Method::Wrapped
+
+# NOTE:
+# the way this item is initialized, this
+# really does not follow the standard
+# practices of attributes, but we put
+# it here for completeness
+Class::MOP::Method::Wrapped->meta->add_attribute(
+ Class::MOP::Attribute->new('modifier_table' => (
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Method::Generated
+
+Class::MOP::Method::Generated->meta->add_attribute(
+ Class::MOP::Attribute->new('is_inline' => (
+ reader => { 'is_inline' => \&Class::MOP::Method::Generated::is_inline },
+ default => 0,
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method::Generated->meta->add_attribute(
+ Class::MOP::Attribute->new('definition_context' => (
+ reader => { 'definition_context' => \&Class::MOP::Method::Generated::definition_context },
+ _definition_context(),
+ ))
+);
+
+
+## --------------------------------------------------------
+## Class::MOP::Method::Inlined
+
+Class::MOP::Method::Inlined->meta->add_attribute(
+ Class::MOP::Attribute->new('_expected_method_class' => (
+ reader => { '_expected_method_class' => \&Class::MOP::Method::Inlined::_expected_method_class },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Method::Accessor
+
+Class::MOP::Method::Accessor->meta->add_attribute(
+ Class::MOP::Attribute->new('attribute' => (
+ reader => {
+ 'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute
+ },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method::Accessor->meta->add_attribute(
+ Class::MOP::Attribute->new('accessor_type' => (
+ reader => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Method::Constructor
+
+Class::MOP::Method::Constructor->meta->add_attribute(
+ Class::MOP::Attribute->new('options' => (
+ reader => {
+ 'options' => \&Class::MOP::Method::Constructor::options
+ },
+ default => sub { +{} },
+ _definition_context(),
+ ))
+);
+
+Class::MOP::Method::Constructor->meta->add_attribute(
+ Class::MOP::Attribute->new('associated_metaclass' => (
+ init_arg => "metaclass", # FIXME alias and rename
+ reader => {
+ 'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass
+ },
+ _definition_context(),
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Overload
+
+Class::MOP::Overload->meta->add_attribute(
+ Class::MOP::Attribute->new(
+ 'operator' => (
+ reader => { 'operator' => \&Class::MOP::Overload::operator },
+ required => 1,
+ _definition_context(),
+ )
+ )
+);
+
+for my $attr (qw( method_name coderef coderef_package coderef_name method )) {
+ Class::MOP::Overload->meta->add_attribute(
+ Class::MOP::Attribute->new(
+ $attr => (
+ reader => { $attr => Class::MOP::Overload->can($attr) },
+ predicate => {
+ 'has_'
+ . $attr => Class::MOP::Overload->can( 'has_' . $attr )
+ },
+ _definition_context(),
+ )
+ )
+ );
+}
+
+Class::MOP::Overload->meta->add_attribute(
+ Class::MOP::Attribute->new(
+ 'associated_metaclass' => (
+ reader => {
+ 'associated_metaclass' =>
+ \&Class::MOP::Overload::associated_metaclass
+ },
+ _definition_context(),
+ )
+ )
+);
+
+## --------------------------------------------------------
+## Class::MOP::Instance
+
+# NOTE:
+# these don't yet do much of anything, but are just
+# included for completeness
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('associated_metaclass',
+ reader => { associated_metaclass => \&Class::MOP::Instance::associated_metaclass },
+ _definition_context(),
+ ),
+);
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('_class_name',
+ init_arg => undef,
+ reader => { _class_name => \&Class::MOP::Instance::_class_name },
+ #lazy => 1, # not yet supported by Class::MOP but out our version does it anyway
+ #default => sub { $_[0]->associated_metaclass->name },
+ _definition_context(),
+ ),
+);
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('attributes',
+ reader => { attributes => \&Class::MOP::Instance::get_all_attributes },
+ _definition_context(),
+ ),
+);
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('slots',
+ reader => { slots => \&Class::MOP::Instance::slots },
+ _definition_context(),
+ ),
+);
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('slot_hash',
+ reader => { slot_hash => \&Class::MOP::Instance::slot_hash },
+ _definition_context(),
+ ),
+);
+
+## --------------------------------------------------------
+## Class::MOP::Object
+
+# need to replace the meta method there with a real meta method object
+Class::MOP::Object->meta->_add_meta_method('meta');
+
+## --------------------------------------------------------
+## Class::MOP::Mixin
+
+# need to replace the meta method there with a real meta method object
+Class::MOP::Mixin->meta->_add_meta_method('meta');
+
+require Class::MOP::Deprecated unless our $no_deprecated;
+
+# we need the meta instance of the meta instance to be created now, in order
+# for the constructor to be able to use it
+Class::MOP::Instance->meta->get_meta_instance;
+
+# pretend the add_method never happened. it hasn't yet affected anything
+undef Class::MOP::Instance->meta->{_package_cache_flag};
+
+## --------------------------------------------------------
+## Now close all the Class::MOP::* classes
+
+# NOTE: we don't need to inline the accessors this only lengthens the compile
+# time of the MOP, and gives us no actual benefits.
+
+$_->meta->make_immutable(
+ inline_constructor => 0,
+ constructor_name => "_new",
+ inline_accessors => 0,
+) for qw/
+ Class::MOP::Package
+ Class::MOP::Module
+ Class::MOP::Class
+
+ Class::MOP::Attribute
+ Class::MOP::Method
+ Class::MOP::Instance
+
+ Class::MOP::Object
+
+ Class::MOP::Method::Generated
+ Class::MOP::Method::Inlined
+
+ Class::MOP::Method::Accessor
+ Class::MOP::Method::Constructor
+ Class::MOP::Method::Wrapped
+
+ Class::MOP::Method::Meta
+
+ Class::MOP::Overload
+/;
+
+$_->meta->make_immutable(
+ inline_constructor => 0,
+ constructor_name => undef,
+ inline_accessors => 0,
+) for qw/
+ Class::MOP::Mixin
+ Class::MOP::Mixin::AttributeCore
+ Class::MOP::Mixin::HasAttributes
+ Class::MOP::Mixin::HasMethods
+ Class::MOP::Mixin::HasOverloads
+/;
+
+1;
+
+# ABSTRACT: A Meta Object Protocol for Perl 5
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP - A Meta Object Protocol for Perl 5
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This module is a fully functioning meta object protocol for the
+Perl 5 object system. It makes no attempt to change the behavior or
+characteristics of the Perl 5 object system, only to create a
+protocol for its manipulation and introspection.
+
+That said, it does attempt to create the tools for building a rich set
+of extensions to the Perl 5 object system. Every attempt has been made
+to abide by the spirit of the Perl 5 object system that we all know
+and love.
+
+This documentation is sparse on conceptual details. We suggest looking
+at the items listed in the L<SEE ALSO> section for more
+information. In particular the book "The Art of the Meta Object
+Protocol" was very influential in the development of this system.
+
+=head2 What is a Meta Object Protocol?
+
+A meta object protocol is an API to an object system.
+
+To be more specific, it abstracts the components of an object system
+(classes, object, methods, object attributes, etc.). These
+abstractions can then be used to inspect and manipulate the object
+system which they describe.
+
+It can be said that there are two MOPs for any object system; the
+implicit MOP and the explicit MOP. The implicit MOP handles things
+like method dispatch or inheritance, which happen automatically as
+part of how the object system works. The explicit MOP typically
+handles the introspection/reflection features of the object system.
+
+All object systems have implicit MOPs. Without one, they would not
+work. Explicit MOPs are much less common, and depending on the
+language can vary from restrictive (Reflection in Java or C#) to wide
+open (CLOS is a perfect example).
+
+=head2 Yet Another Class Builder! Why?
+
+This is B<not> a class builder so much as a I<class builder
+B<builder>>. The intent is that an end user will not use this module
+directly, but instead this module is used by module authors to build
+extensions and features onto the Perl 5 object system.
+
+This system is used by L<Moose>, which supplies a powerful class
+builder system built entirely on top of C<Class::MOP>.
+
+=head2 Who is this module for?
+
+This module is for anyone who has ever created or wanted to create a
+module for the Class:: namespace. The tools which this module provides
+make doing complex Perl 5 wizardry simpler, by removing such barriers
+as the need to hack symbol tables, or understand the fine details of
+method dispatch.
+
+=head2 What changes do I have to make to use this module?
+
+This module was designed to be as unobtrusive as possible. Many of its
+features are accessible without B<any> change to your existing
+code. It is meant to be a complement to your existing code and not an
+intrusion on your code base. Unlike many other B<Class::> modules,
+this module B<does not> require you subclass it, or even that you
+C<use> it in within your module's package.
+
+The only features which require additions to your code are the
+attribute handling and instance construction features, and these are
+both completely optional features. The only reason for this is because
+Perl 5's object system does not actually have these features built
+in. More information about this feature can be found below.
+
+=head2 About Performance
+
+It is a common misconception that explicit MOPs are a performance hit.
+This is not a universal truth, it is a side-effect of some specific
+implementations. For instance, using Java reflection is slow because
+the JVM cannot take advantage of any compiler optimizations, and the
+JVM has to deal with much more runtime type information as well.
+
+Reflection in C# is marginally better as it was designed into the
+language and runtime (the CLR). In contrast, CLOS (the Common Lisp
+Object System) was built to support an explicit MOP, and so
+performance is tuned for it.
+
+This library in particular does its absolute best to avoid putting
+B<any> drain at all upon your code's performance. In fact, by itself
+it does nothing to affect your existing code. So you only pay for what
+you actually use.
+
+=head2 About Metaclass compatibility
+
+This module makes sure that all metaclasses created are both upwards
+and downwards compatible. The topic of metaclass compatibility is
+highly esoteric and is something only encountered when doing deep and
+involved metaclass hacking. There are two basic kinds of metaclass
+incompatibility; upwards and downwards.
+
+Upwards metaclass compatibility means that the metaclass of a
+given class is either the same as (or a subclass of) all of the
+metaclasses of the class's ancestors.
+
+Downward metaclass compatibility means that the metaclasses of a
+given class's ancestors are all the same as (or a subclass of) that
+class's metaclass.
+
+Here is a diagram showing a set of two classes (C<A> and C<B>) and
+two metaclasses (C<Meta::A> and C<Meta::B>) which have correct
+metaclass compatibility both upwards and downwards.
+
+ +---------+ +---------+
+ | Meta::A |<----| Meta::B | <....... (instance of )
+ +---------+ +---------+ <------- (inherits from)
+ ^ ^
+ : :
+ +---------+ +---------+
+ | A |<----| B |
+ +---------+ +---------+
+
+In actuality, I<all> of a class's metaclasses must be compatible,
+not just the class metaclass. That includes the instance, attribute,
+and method metaclasses, as well as the constructor and destructor
+classes.
+
+C<Class::MOP> will attempt to fix some simple types of
+incompatibilities. If all the metaclasses for the parent class are
+I<subclasses> of the child's metaclasses then we can simply replace
+the child's metaclasses with the parent's. In addition, if the child
+is missing a metaclass that the parent has, we can also just make the
+child use the parent's metaclass.
+
+As I said this is a highly esoteric topic and one you will only run
+into if you do a lot of subclassing of L<Class::MOP::Class>. If you
+are interested in why this is an issue see the paper I<Uniform and
+safe metaclass composition> linked to in the L<SEE ALSO> section of
+this document.
+
+=head2 Using custom metaclasses
+
+Always use the L<metaclass> pragma when using a custom metaclass, this
+will ensure the proper initialization order and not accidentally
+create an incorrect type of metaclass for you. This is a very rare
+problem, and one which can only occur if you are doing deep metaclass
+programming. So in other words, don't worry about it.
+
+Note that if you're using L<Moose> we encourage you to I<not> use the
+L<metaclass> pragma, and instead use L<Moose::Util::MetaRole> to apply
+roles to a class's metaclasses. This topic is covered at length in
+various L<Moose::Cookbook> recipes.
+
+=head1 PROTOCOLS
+
+The meta-object protocol is divided into 4 main sub-protocols:
+
+=head2 The Class protocol
+
+This provides a means of manipulating and introspecting a Perl 5
+class. It handles symbol table hacking for you, and provides a rich
+set of methods that go beyond simple package introspection.
+
+See L<Class::MOP::Class> for more details.
+
+=head2 The Attribute protocol
+
+This provides a consistent representation for an attribute of a Perl 5
+class. Since there are so many ways to create and handle attributes in
+Perl 5 OO, the Attribute protocol provide as much of a unified
+approach as possible. Of course, you are always free to extend this
+protocol by subclassing the appropriate classes.
+
+See L<Class::MOP::Attribute> for more details.
+
+=head2 The Method protocol
+
+This provides a means of manipulating and introspecting methods in the
+Perl 5 object system. As with attributes, there are many ways to
+approach this topic, so we try to keep it pretty basic, while still
+making it possible to extend the system in many ways.
+
+See L<Class::MOP::Method> for more details.
+
+=head2 The Instance protocol
+
+This provides a layer of abstraction for creating object instances.
+Since the other layers use this protocol, it is relatively easy to
+change the type of your instances from the default hash reference to
+some other type of reference. Several examples are provided in the
+F<examples/> directory included in this distribution.
+
+See L<Class::MOP::Instance> for more details.
+
+=head1 FUNCTIONS
+
+Note that this module does not export any constants or functions.
+
+=head2 Utility functions
+
+Note that these are all called as B<functions, not methods>.
+
+=over 4
+
+=item B<Class::MOP::get_code_info($code)>
+
+This function returns two values, the name of the package the C<$code>
+is from and the name of the C<$code> itself. This is used by several
+elements of the MOP to determine where a given C<$code> reference is
+from.
+
+=item B<Class::MOP::class_of($instance_or_class_name)>
+
+This will return the metaclass of the given instance or class name. If the
+class lacks a metaclass, no metaclass will be initialized, and C<undef> will be
+returned.
+
+You should almost certainly be using
+L<C<Moose::Util::find_meta>|Moose::Util/find_meta> instead.
+
+=back
+
+=head2 Metaclass cache functions
+
+C<Class::MOP> holds a cache of metaclasses. The following are functions
+(B<not methods>) which can be used to access that cache. It is not
+recommended that you mess with these. Bad things could happen, but if
+you are brave and willing to risk it: go for it!
+
+=over 4
+
+=item B<Class::MOP::get_all_metaclasses>
+
+This will return a hash of all the metaclass instances that have
+been cached by L<Class::MOP::Class>, keyed by the package name.
+
+=item B<Class::MOP::get_all_metaclass_instances>
+
+This will return a list of all the metaclass instances that have
+been cached by L<Class::MOP::Class>.
+
+=item B<Class::MOP::get_all_metaclass_names>
+
+This will return a list of all the metaclass names that have
+been cached by L<Class::MOP::Class>.
+
+=item B<Class::MOP::get_metaclass_by_name($name)>
+
+This will return a cached L<Class::MOP::Class> instance, or nothing
+if no metaclass exists with that C<$name>.
+
+=item B<Class::MOP::store_metaclass_by_name($name, $meta)>
+
+This will store a metaclass in the cache at the supplied C<$key>.
+
+=item B<Class::MOP::weaken_metaclass($name)>
+
+In rare cases (e.g. anonymous metaclasses) it is desirable to
+store a weakened reference in the metaclass cache. This
+function will weaken the reference to the metaclass stored
+in C<$name>.
+
+=item B<Class::MOP::metaclass_is_weak($name)>
+
+Returns true if the metaclass for C<$name> has been weakened
+(via C<weaken_metaclass>).
+
+=item B<Class::MOP::does_metaclass_exist($name)>
+
+This will return true of there exists a metaclass stored in the
+C<$name> key, and return false otherwise.
+
+=item B<Class::MOP::remove_metaclass_by_name($name)>
+
+This will remove the metaclass stored in the C<$name> key.
+
+=back
+
+Some utility functions (such as C<Class::MOP::load_class>) that were
+previously defined in C<Class::MOP> regarding loading of classes have been
+extracted to L<Class::Load>. Please see L<Class::Load> for documentation.
+
+=head1 SEE ALSO
+
+=head2 Books
+
+There are very few books out on Meta Object Protocols and Metaclasses
+because it is such an esoteric topic. The following books are really
+the only ones I have found. If you know of any more, B<I<please>>
+email me and let me know, I would love to hear about them.
+
+=over 4
+
+=item I<The Art of the Meta Object Protocol>
+
+=item I<Advances in Object-Oriented Metalevel Architecture and Reflection>
+
+=item I<Putting MetaClasses to Work>
+
+=item I<Smalltalk: The Language>
+
+=back
+
+=head2 Papers
+
+=over 4
+
+=item "Uniform and safe metaclass composition"
+
+An excellent paper by the people who brought us the original Traits paper.
+This paper is on how Traits can be used to do safe metaclass composition,
+and offers an excellent introduction section which delves into the topic of
+metaclass compatibility.
+
+L<http://scg.unibe.ch/archive/papers/Duca05ySafeMetaclassTrait.pdf>
+
+=item "Safe Metaclass Programming"
+
+This paper seems to precede the above paper, and propose a mix-in based
+approach as opposed to the Traits based approach. Both papers have similar
+information on the metaclass compatibility problem space.
+
+L<http://citeseer.ist.psu.edu/37617.html>
+
+=back
+
+=head2 Prior Art
+
+=over 4
+
+=item The Perl 6 MetaModel work in the Pugs project
+
+=over 4
+
+=item L<http://svn.openfoundry.org/pugs/misc/Perl-MetaModel/>
+
+=item L<http://github.com/perl6/p5-modules/tree/master/Perl6-ObjectSpace/>
+
+=back
+
+=back
+
+=head2 Articles
+
+=over 4
+
+=item CPAN Module Review of Class::MOP
+
+L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
+
+=back
+
+=head1 SIMILAR MODULES
+
+As I have said above, this module is a class-builder-builder, so it is
+not the same thing as modules like L<Class::Accessor> and
+L<Class::MethodMaker>. That being said there are very few modules on CPAN
+with similar goals to this module. The one I have found which is most
+like this module is L<Class::Meta>, although its philosophy and the MOP it
+creates are very different from this modules.
+
+=head1 BUGS
+
+All complex software has bugs lurking in it, and this module is no
+exception.
+
+Please report any bugs to C<bug-class-mop@rt.cpan.org>, or through the
+web interface at L<http://rt.cpan.org>.
+
+You can also discuss feature requests or possible bugs on the Moose
+mailing list (moose@perl.org) or on IRC at
+L<irc://irc.perl.org/#moose>.
+
+=head1 ACKNOWLEDGEMENTS
+
+=over 4
+
+=item Rob Kinyon
+
+Thanks to Rob for actually getting the development of this module kick-started.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Attribute.pm b/lib/Class/MOP/Attribute.pm
new file mode 100644
index 0000000..c5c4995
--- /dev/null
+++ b/lib/Class/MOP/Attribute.pm
@@ -0,0 +1,1100 @@
+package Class::MOP::Attribute;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Class::MOP::Method::Accessor;
+
+use Carp 'confess';
+use Scalar::Util 'blessed', 'weaken';
+use Try::Tiny;
+
+use parent 'Class::MOP::Object', 'Class::MOP::Mixin::AttributeCore';
+
+# NOTE: (meta-circularity)
+# This method will be replaced in the
+# boostrap section of Class::MOP, by
+# a new version which uses the
+# &Class::MOP::Class::construct_instance
+# method to build an attribute meta-object
+# which itself is described with attribute
+# meta-objects.
+# - Ain't meta-circularity grand? :)
+sub new {
+ my ( $class, @args ) = @_;
+
+ unshift @args, "name" if @args % 2 == 1;
+ my %options = @args;
+
+ my $name = $options{name};
+
+ (defined $name)
+ || $class->_throw_exception( MOPAttributeNewNeedsAttributeName => class => $class,
+ params => \%options
+ );
+
+ $options{init_arg} = $name
+ if not exists $options{init_arg};
+ if(exists $options{builder}){
+ $class->_throw_exception( BuilderMustBeAMethodName => class => $class,
+ params => \%options
+ )
+ if ref $options{builder} || !(defined $options{builder});
+ $class->_throw_exception( BothBuilderAndDefaultAreNotAllowed => class => $class,
+ params => \%options
+ )
+ if exists $options{default};
+ } else {
+ ($class->is_default_a_coderef(\%options))
+ || $class->_throw_exception( ReferencesAreNotAllowedAsDefault => class => $class,
+ params => \%options,
+ attribute_name => $options{name}
+ )
+ if exists $options{default} && ref $options{default};
+ }
+
+ if( $options{required} and not( defined($options{builder}) || defined($options{init_arg}) || exists $options{default} ) ) {
+ $class->_throw_exception( RequiredAttributeLacksInitialization => class => $class,
+ params => \%options
+ );
+ }
+
+ $class->_new(\%options);
+}
+
+sub _new {
+ my $class = shift;
+
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $options = @_ == 1 ? $_[0] : {@_};
+
+ bless {
+ 'name' => $options->{name},
+ 'accessor' => $options->{accessor},
+ 'reader' => $options->{reader},
+ 'writer' => $options->{writer},
+ 'predicate' => $options->{predicate},
+ 'clearer' => $options->{clearer},
+ 'builder' => $options->{builder},
+ 'init_arg' => $options->{init_arg},
+ exists $options->{default}
+ ? ('default' => $options->{default})
+ : (),
+ 'initializer' => $options->{initializer},
+ 'definition_context' => $options->{definition_context},
+ # keep a weakened link to the
+ # class we are associated with
+ 'associated_class' => undef,
+ # and a list of the methods
+ # associated with this attr
+ 'associated_methods' => [],
+ # this let's us keep track of
+ # our order inside the associated
+ # class
+ 'insertion_order' => undef,
+ }, $class;
+}
+
+# NOTE:
+# this is a primitive (and kludgy) clone operation
+# for now, it will be replaced in the Class::MOP
+# bootstrap with a proper one, however we know
+# that this one will work fine for now.
+sub clone {
+ my $self = shift;
+ my %options = @_;
+ (blessed($self))
+ || confess "Can only clone an instance";
+ # this implementation is overwritten by the bootstrap process,
+ # so this exception will never trigger. If it ever does occur,
+ # it indicates a gigantic problem with the most internal parts
+ # of Moose, so we wouldn't want a Moose-based exception object anyway
+
+ return bless { %{$self}, %options } => ref($self);
+}
+
+sub initialize_instance_slot {
+ my ($self, $meta_instance, $instance, $params) = @_;
+ my $init_arg = $self->{'init_arg'};
+
+ # try to fetch the init arg from the %params ...
+
+ # if nothing was in the %params, we can use the
+ # attribute's default value (if it has one)
+ if(defined $init_arg and exists $params->{$init_arg}){
+ $self->_set_initial_slot_value(
+ $meta_instance,
+ $instance,
+ $params->{$init_arg},
+ );
+ }
+ elsif (exists $self->{'default'}) {
+ $self->_set_initial_slot_value(
+ $meta_instance,
+ $instance,
+ $self->default($instance),
+ );
+ }
+ elsif (defined( my $builder = $self->{'builder'})) {
+ if ($builder = $instance->can($builder)) {
+ $self->_set_initial_slot_value(
+ $meta_instance,
+ $instance,
+ $instance->$builder,
+ );
+ }
+ else {
+ $self->_throw_exception( BuilderMethodNotSupportedForAttribute => attribute => $self,
+ instance => $instance
+ );
+ }
+ }
+}
+
+sub _set_initial_slot_value {
+ my ($self, $meta_instance, $instance, $value) = @_;
+
+ my $slot_name = $self->name;
+
+ return $meta_instance->set_slot_value($instance, $slot_name, $value)
+ unless $self->has_initializer;
+
+ my $callback = $self->_make_initializer_writer_callback(
+ $meta_instance, $instance, $slot_name
+ );
+
+ my $initializer = $self->initializer;
+
+ # most things will just want to set a value, so make it first arg
+ $instance->$initializer($value, $callback, $self);
+}
+
+sub _make_initializer_writer_callback {
+ my $self = shift;
+ my ($meta_instance, $instance, $slot_name) = @_;
+
+ return sub {
+ $meta_instance->set_slot_value($instance, $slot_name, $_[0]);
+ };
+}
+
+sub get_read_method {
+ my $self = shift;
+ my $reader = $self->reader || $self->accessor;
+ # normal case ...
+ return $reader unless ref $reader;
+ # the HASH ref case
+ my ($name) = %$reader;
+ return $name;
+}
+
+sub get_write_method {
+ my $self = shift;
+ my $writer = $self->writer || $self->accessor;
+ # normal case ...
+ return $writer unless ref $writer;
+ # the HASH ref case
+ my ($name) = %$writer;
+ return $name;
+}
+
+sub get_read_method_ref {
+ my $self = shift;
+ if ((my $reader = $self->get_read_method) && $self->associated_class) {
+ return $self->associated_class->get_method($reader);
+ }
+ else {
+ my $code = sub { $self->get_value(@_) };
+ if (my $class = $self->associated_class) {
+ return $class->method_metaclass->wrap(
+ $code,
+ package_name => $class->name,
+ name => '__ANON__'
+ );
+ }
+ else {
+ return $code;
+ }
+ }
+}
+
+sub get_write_method_ref {
+ my $self = shift;
+ if ((my $writer = $self->get_write_method) && $self->associated_class) {
+ return $self->associated_class->get_method($writer);
+ }
+ else {
+ my $code = sub { $self->set_value(@_) };
+ if (my $class = $self->associated_class) {
+ return $class->method_metaclass->wrap(
+ $code,
+ package_name => $class->name,
+ name => '__ANON__'
+ );
+ }
+ else {
+ return $code;
+ }
+ }
+}
+
+# slots
+
+sub slots { (shift)->name }
+
+# class association
+
+sub attach_to_class {
+ my ($self, $class) = @_;
+ (blessed($class) && $class->isa('Class::MOP::Class'))
+ || $self->_throw_exception( AttachToClassNeedsAClassMOPClassInstanceOrASubclass => attribute => $self,
+ class => $class
+ );
+ weaken($self->{'associated_class'} = $class);
+}
+
+sub detach_from_class {
+ my $self = shift;
+ $self->{'associated_class'} = undef;
+}
+
+# method association
+
+sub associate_method {
+ my ($self, $method) = @_;
+ push @{$self->{'associated_methods'}} => $method;
+}
+
+## Slot management
+
+sub set_initial_value {
+ my ($self, $instance, $value) = @_;
+ $self->_set_initial_slot_value(
+ Class::MOP::Class->initialize(ref($instance))->get_meta_instance,
+ $instance,
+ $value
+ );
+}
+
+sub set_value { shift->set_raw_value(@_) }
+
+sub set_raw_value {
+ my $self = shift;
+ my ($instance, $value) = @_;
+
+ my $mi = Class::MOP::Class->initialize(ref($instance))->get_meta_instance;
+ return $mi->set_slot_value($instance, $self->name, $value);
+}
+
+sub _inline_set_value {
+ my $self = shift;
+ return $self->_inline_instance_set(@_) . ';';
+}
+
+sub _inline_instance_set {
+ my $self = shift;
+ my ($instance, $value) = @_;
+
+ my $mi = $self->associated_class->get_meta_instance;
+ return $mi->inline_set_slot_value($instance, $self->name, $value);
+}
+
+sub get_value { shift->get_raw_value(@_) }
+
+sub get_raw_value {
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $mi = Class::MOP::Class->initialize(ref($instance))->get_meta_instance;
+ return $mi->get_slot_value($instance, $self->name);
+}
+
+sub _inline_get_value {
+ my $self = shift;
+ return $self->_inline_instance_get(@_) . ';';
+}
+
+sub _inline_instance_get {
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $mi = $self->associated_class->get_meta_instance;
+ return $mi->inline_get_slot_value($instance, $self->name);
+}
+
+sub has_value {
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $mi = Class::MOP::Class->initialize(ref($instance))->get_meta_instance;
+ return $mi->is_slot_initialized($instance, $self->name);
+}
+
+sub _inline_has_value {
+ my $self = shift;
+ return $self->_inline_instance_has(@_) . ';';
+}
+
+sub _inline_instance_has {
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $mi = $self->associated_class->get_meta_instance;
+ return $mi->inline_is_slot_initialized($instance, $self->name);
+}
+
+sub clear_value {
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $mi = Class::MOP::Class->initialize(ref($instance))->get_meta_instance;
+ return $mi->deinitialize_slot($instance, $self->name);
+}
+
+sub _inline_clear_value {
+ my $self = shift;
+ return $self->_inline_instance_clear(@_) . ';';
+}
+
+sub _inline_instance_clear {
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $mi = $self->associated_class->get_meta_instance;
+ return $mi->inline_deinitialize_slot($instance, $self->name);
+}
+
+## load em up ...
+
+sub accessor_metaclass { 'Class::MOP::Method::Accessor' }
+
+sub _process_accessors {
+ my ($self, $type, $accessor, $generate_as_inline_methods) = @_;
+
+ my $method_ctx = { %{ $self->definition_context || {} } };
+
+ if (ref($accessor)) {
+ (ref($accessor) eq 'HASH')
+ || $self->_throw_exception( BadOptionFormat => attribute => $self,
+ option_value => $accessor,
+ option_name => $type
+ );
+
+ my ($name, $method) = %{$accessor};
+
+ $method_ctx->{description} = $self->_accessor_description($name, $type);
+
+ $method = $self->accessor_metaclass->wrap(
+ $method,
+ attribute => $self,
+ package_name => $self->associated_class->name,
+ name => $name,
+ associated_metaclass => $self->associated_class,
+ definition_context => $method_ctx,
+ );
+ $self->associate_method($method);
+ return ($name, $method);
+ }
+ else {
+ my $inline_me = ($generate_as_inline_methods && $self->associated_class->instance_metaclass->is_inlinable);
+ my $method;
+ try {
+ $method_ctx->{description} = $self->_accessor_description($accessor, $type);
+
+ $method = $self->accessor_metaclass->new(
+ attribute => $self,
+ is_inline => $inline_me,
+ accessor_type => $type,
+ package_name => $self->associated_class->name,
+ name => $accessor,
+ associated_metaclass => $self->associated_class,
+ definition_context => $method_ctx,
+ );
+ }
+ catch {
+ $self->_throw_exception( CouldNotCreateMethod => attribute => $self,
+ option_value => $accessor,
+ option_name => $type,
+ error => $_
+ );
+ };
+ $self->associate_method($method);
+ return ($accessor, $method);
+ }
+}
+
+sub _accessor_description {
+ my $self = shift;
+ my ($name, $type) = @_;
+
+ my $desc = "$type " . $self->associated_class->name . "::$name";
+ if ( $name ne $self->name ) {
+ $desc .= " of attribute " . $self->name;
+ }
+
+ return $desc;
+}
+
+sub install_accessors {
+ my $self = shift;
+ my $inline = shift;
+ my $class = $self->associated_class;
+
+ $class->add_method(
+ $self->_process_accessors('accessor' => $self->accessor(), $inline)
+ ) if $self->has_accessor();
+
+ $class->add_method(
+ $self->_process_accessors('reader' => $self->reader(), $inline)
+ ) if $self->has_reader();
+
+ $class->add_method(
+ $self->_process_accessors('writer' => $self->writer(), $inline)
+ ) if $self->has_writer();
+
+ $class->add_method(
+ $self->_process_accessors('predicate' => $self->predicate(), $inline)
+ ) if $self->has_predicate();
+
+ $class->add_method(
+ $self->_process_accessors('clearer' => $self->clearer(), $inline)
+ ) if $self->has_clearer();
+
+ return;
+}
+
+{
+ my $_remove_accessor = sub {
+ my ($accessor, $class) = @_;
+ if (ref($accessor) && ref($accessor) eq 'HASH') {
+ ($accessor) = keys %{$accessor};
+ }
+ my $method = $class->get_method($accessor);
+ $class->remove_method($accessor)
+ if (ref($method) && $method->isa('Class::MOP::Method::Accessor'));
+ };
+
+ sub remove_accessors {
+ my $self = shift;
+ # TODO:
+ # we really need to make sure to remove from the
+ # associates methods here as well. But this is
+ # such a slimly used method, I am not worried
+ # about it right now.
+ $_remove_accessor->($self->accessor(), $self->associated_class()) if $self->has_accessor();
+ $_remove_accessor->($self->reader(), $self->associated_class()) if $self->has_reader();
+ $_remove_accessor->($self->writer(), $self->associated_class()) if $self->has_writer();
+ $_remove_accessor->($self->predicate(), $self->associated_class()) if $self->has_predicate();
+ $_remove_accessor->($self->clearer(), $self->associated_class()) if $self->has_clearer();
+ return;
+ }
+
+}
+
+1;
+
+# ABSTRACT: Attribute Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Attribute - Attribute Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 SYNOPSIS
+
+ Class::MOP::Attribute->new(
+ foo => (
+ accessor => 'foo', # dual purpose get/set accessor
+ predicate => 'has_foo', # predicate check for defined-ness
+ init_arg => '-foo', # class->new will look for a -foo key
+ default => 'BAR IS BAZ!' # if no -foo key is provided, use this
+ )
+ );
+
+ Class::MOP::Attribute->new(
+ bar => (
+ reader => 'bar', # getter
+ writer => 'set_bar', # setter
+ predicate => 'has_bar', # predicate check for defined-ness
+ init_arg => ':bar', # class->new will look for a :bar key
+ # no default value means it is undef
+ )
+ );
+
+=head1 DESCRIPTION
+
+The Attribute Protocol is almost entirely an invention of
+C<Class::MOP>. Perl 5 does not have a consistent notion of
+attributes. There are so many ways in which this is done, and very few
+(if any) are easily discoverable by this module.
+
+With that said, this module attempts to inject some order into this
+chaos, by introducing a consistent API which can be used to create
+object attributes.
+
+=head1 METHODS
+
+=head2 Creation
+
+=over 4
+
+=item B<< Class::MOP::Attribute->new($name, ?%options) >>
+
+An attribute must (at the very least), have a C<$name>. All other
+C<%options> are added as key-value pairs.
+
+=over 8
+
+=item * init_arg
+
+This is a string value representing the expected key in an
+initialization hash. For instance, if we have an C<init_arg> value of
+C<-foo>, then the following code will Just Work.
+
+ MyClass->meta->new_object( -foo => 'Hello There' );
+
+If an init_arg is not assigned, it will automatically use the
+attribute's name. If C<init_arg> is explicitly set to C<undef>, the
+attribute cannot be specified during initialization.
+
+=item * builder
+
+This provides the name of a method that will be called to initialize
+the attribute. This method will be called on the object after it is
+constructed. It is expected to return a valid value for the attribute.
+
+=item * default
+
+This can be used to provide an explicit default for initializing the
+attribute. If the default you provide is a subroutine reference, then
+this reference will be called I<as a method> on the object.
+
+If the value is a simple scalar (string or number), then it can be
+just passed as is. However, if you wish to initialize it with a HASH
+or ARRAY ref, then you need to wrap that inside a subroutine
+reference:
+
+ Class::MOP::Attribute->new(
+ 'foo' => (
+ default => sub { [] },
+ )
+ );
+
+ # or ...
+
+ Class::MOP::Attribute->new(
+ 'foo' => (
+ default => sub { {} },
+ )
+ );
+
+If you wish to initialize an attribute with a subroutine reference
+itself, then you need to wrap that in a subroutine as well:
+
+ Class::MOP::Attribute->new(
+ 'foo' => (
+ default => sub {
+ sub { print "Hello World" }
+ },
+ )
+ );
+
+And lastly, if the value of your attribute is dependent upon some
+other aspect of the instance structure, then you can take advantage of
+the fact that when the C<default> value is called as a method:
+
+ Class::MOP::Attribute->new(
+ 'object_identity' => (
+ default => sub { Scalar::Util::refaddr( $_[0] ) },
+ )
+ );
+
+Note that there is no guarantee that attributes are initialized in any
+particular order, so you cannot rely on the value of some other
+attribute when generating the default.
+
+=item * initializer
+
+This option can be either a method name or a subroutine
+reference. This method will be called when setting the attribute's
+value in the constructor. Unlike C<default> and C<builder>, the
+initializer is only called when a value is provided to the
+constructor. The initializer allows you to munge this value during
+object construction.
+
+The initializer is called as a method with three arguments. The first
+is the value that was passed to the constructor. The second is a
+subroutine reference that can be called to actually set the
+attribute's value, and the last is the associated
+C<Class::MOP::Attribute> object.
+
+This contrived example shows an initializer that sets the attribute to
+twice the given value.
+
+ Class::MOP::Attribute->new(
+ 'doubled' => (
+ initializer => sub {
+ my ( $self, $value, $set, $attr ) = @_;
+ $set->( $value * 2 );
+ },
+ )
+ );
+
+Since an initializer can be a method name, you can easily make
+attribute initialization use the writer:
+
+ Class::MOP::Attribute->new(
+ 'some_attr' => (
+ writer => 'some_attr',
+ initializer => 'some_attr',
+ )
+ );
+
+Your writer (actually, a wrapper around the writer, using
+L<method modifications|Moose::Manual::MethodModifiers>) will need to examine
+C<@_> and determine under which
+context it is being called:
+
+ around 'some_attr' => sub {
+ my $orig = shift;
+ my $self = shift;
+ # $value is not defined if being called as a reader
+ # $setter and $attr are only defined if being called as an initializer
+ my ($value, $setter, $attr) = @_;
+
+ # the reader behaves normally
+ return $self->$orig if not @_;
+
+ # mutate $value as desired
+ # $value = <something($value);
+
+ # if called as an initializer, set the value and we're done
+ return $setter->($row) if $setter;
+
+ # otherwise, call the real writer with the new value
+ $self->$orig($row);
+ };
+
+=back
+
+The C<accessor>, C<reader>, C<writer>, C<predicate> and C<clearer>
+options all accept the same parameters. You can provide the name of
+the method, in which case an appropriate default method will be
+generated for you. Or instead you can also provide hash reference
+containing exactly one key (the method name) and one value. The value
+should be a subroutine reference, which will be installed as the
+method itself.
+
+=over 8
+
+=item * accessor
+
+An C<accessor> is a standard Perl-style read/write accessor. It will
+return the value of the attribute, and if a value is passed as an
+argument, it will assign that value to the attribute.
+
+Note that C<undef> is a legitimate value, so this will work:
+
+ $object->set_something(undef);
+
+=item * reader
+
+This is a basic read-only accessor. It returns the value of the
+attribute.
+
+=item * writer
+
+This is a basic write accessor, it accepts a single argument, and
+assigns that value to the attribute.
+
+Note that C<undef> is a legitimate value, so this will work:
+
+ $object->set_something(undef);
+
+=item * predicate
+
+The predicate method returns a boolean indicating whether or not the
+attribute has been explicitly set.
+
+Note that the predicate returns true even if the attribute was set to
+a false value (C<0> or C<undef>).
+
+=item * clearer
+
+This method will uninitialize the attribute. After an attribute is
+cleared, its C<predicate> will return false.
+
+=item * definition_context
+
+Mostly, this exists as a hook for the benefit of Moose.
+
+This option should be a hash reference containing several keys which
+will be used when inlining the attribute's accessors. The keys should
+include C<line>, the line number where the attribute was created, and
+either C<file> or C<description>.
+
+This information will ultimately be used when eval'ing inlined
+accessor code so that error messages report a useful line and file
+name.
+
+=back
+
+=item B<< $attr->clone(%options) >>
+
+This clones the attribute. Any options you provide will override the
+settings of the original attribute. You can change the name of the new
+attribute by passing a C<name> key in C<%options>.
+
+=back
+
+=head2 Informational
+
+These are all basic read-only accessors for the values passed into
+the constructor.
+
+=over 4
+
+=item B<< $attr->name >>
+
+Returns the attribute's name.
+
+=item B<< $attr->accessor >>
+
+=item B<< $attr->reader >>
+
+=item B<< $attr->writer >>
+
+=item B<< $attr->predicate >>
+
+=item B<< $attr->clearer >>
+
+The C<accessor>, C<reader>, C<writer>, C<predicate>, and C<clearer>
+methods all return exactly what was passed to the constructor, so it
+can be either a string containing a method name, or a hash reference.
+
+=item B<< $attr->initializer >>
+
+Returns the initializer as passed to the constructor, so this may be
+either a method name or a subroutine reference.
+
+=item B<< $attr->init_arg >>
+
+=item B<< $attr->is_default_a_coderef >>
+
+=item B<< $attr->builder >>
+
+=item B<< $attr->default($instance) >>
+
+The C<$instance> argument is optional. If you don't pass it, the
+return value for this method is exactly what was passed to the
+constructor, either a simple scalar or a subroutine reference.
+
+If you I<do> pass an C<$instance> and the default is a subroutine
+reference, then the reference is called as a method on the
+C<$instance> and the generated value is returned.
+
+=item B<< $attr->slots >>
+
+Return a list of slots required by the attribute. This is usually just
+one, the name of the attribute.
+
+A slot is the name of the hash key used to store the attribute in an
+object instance.
+
+=item B<< $attr->get_read_method >>
+
+=item B<< $attr->get_write_method >>
+
+Returns the name of a method suitable for reading or writing the value
+of the attribute in the associated class.
+
+If an attribute is read- or write-only, then these methods can return
+C<undef> as appropriate.
+
+=item B<< $attr->has_read_method >>
+
+=item B<< $attr->has_write_method >>
+
+This returns a boolean indicating whether the attribute has a I<named>
+read or write method.
+
+=item B<< $attr->get_read_method_ref >>
+
+=item B<< $attr->get_write_method_ref >>
+
+Returns the subroutine reference of a method suitable for reading or
+writing the attribute's value in the associated class. These methods
+always return a subroutine reference, regardless of whether or not the
+attribute is read- or write-only.
+
+=item B<< $attr->insertion_order >>
+
+If this attribute has been inserted into a class, this returns a zero
+based index regarding the order of insertion.
+
+=back
+
+=head2 Informational predicates
+
+These are all basic predicate methods for the values passed into C<new>.
+
+=over 4
+
+=item B<< $attr->has_accessor >>
+
+=item B<< $attr->has_reader >>
+
+=item B<< $attr->has_writer >>
+
+=item B<< $attr->has_predicate >>
+
+=item B<< $attr->has_clearer >>
+
+=item B<< $attr->has_initializer >>
+
+=item B<< $attr->has_init_arg >>
+
+This will be I<false> if the C<init_arg> was set to C<undef>.
+
+=item B<< $attr->has_default >>
+
+This will be I<false> if the C<default> was set to C<undef>, since
+C<undef> is the default C<default> anyway.
+
+=item B<< $attr->has_builder >>
+
+=item B<< $attr->has_insertion_order >>
+
+This will be I<false> if this attribute has not be inserted into a class
+
+=back
+
+=head2 Value management
+
+These methods are basically "back doors" to the instance, and can be
+used to bypass the regular accessors, but still stay within the MOP.
+
+These methods are not for general use, and should only be used if you
+really know what you are doing.
+
+=over 4
+
+=item B<< $attr->initialize_instance_slot($meta_instance, $instance, $params) >>
+
+This method is used internally to initialize the attribute's slot in
+the object C<$instance>.
+
+The C<$params> is a hash reference of the values passed to the object
+constructor.
+
+It's unlikely that you'll need to call this method yourself.
+
+=item B<< $attr->set_value($instance, $value) >>
+
+Sets the value without going through the accessor. Note that this
+works even with read-only attributes.
+
+=item B<< $attr->set_raw_value($instance, $value) >>
+
+Sets the value with no side effects such as a trigger.
+
+This doesn't actually apply to Class::MOP attributes, only to subclasses.
+
+=item B<< $attr->set_initial_value($instance, $value) >>
+
+Sets the value without going through the accessor. This method is only
+called when the instance is first being initialized.
+
+=item B<< $attr->get_value($instance) >>
+
+Returns the value without going through the accessor. Note that this
+works even with write-only accessors.
+
+=item B<< $attr->get_raw_value($instance) >>
+
+Returns the value without any side effects such as lazy attributes.
+
+Doesn't actually apply to Class::MOP attributes, only to subclasses.
+
+=item B<< $attr->has_value($instance) >>
+
+Return a boolean indicating whether the attribute has been set in
+C<$instance>. This how the default C<predicate> method works.
+
+=item B<< $attr->clear_value($instance) >>
+
+This will clear the attribute's value in C<$instance>. This is what
+the default C<clearer> calls.
+
+Note that this works even if the attribute does not have any
+associated read, write or clear methods.
+
+=back
+
+=head2 Class association
+
+These methods allow you to manage the attributes association with
+the class that contains it. These methods should not be used
+lightly, nor are they very magical, they are mostly used internally
+and by metaclass instances.
+
+=over 4
+
+=item B<< $attr->associated_class >>
+
+This returns the L<Class::MOP::Class> with which this attribute is
+associated, if any.
+
+=item B<< $attr->attach_to_class($metaclass) >>
+
+This method stores a weakened reference to the C<$metaclass> object
+internally.
+
+This method does not remove the attribute from its old class,
+nor does it create any accessors in the new class.
+
+It is probably best to use the L<Class::MOP::Class> C<add_attribute>
+method instead.
+
+=item B<< $attr->detach_from_class >>
+
+This method removes the associate metaclass object from the attribute
+it has one.
+
+This method does not remove the attribute itself from the class, or
+remove its accessors.
+
+It is probably best to use the L<Class::MOP::Class>
+C<remove_attribute> method instead.
+
+=back
+
+=head2 Attribute Accessor generation
+
+=over 4
+
+=item B<< $attr->accessor_metaclass >>
+
+Accessor methods are generated using an accessor metaclass. By
+default, this is L<Class::MOP::Method::Accessor>. This method returns
+the name of the accessor metaclass that this attribute uses.
+
+=item B<< $attr->associate_method($method) >>
+
+This associates a L<Class::MOP::Method> object with the
+attribute. Typically, this is called internally when an attribute
+generates its accessors.
+
+=item B<< $attr->associated_methods >>
+
+This returns the list of methods which have been associated with the
+attribute.
+
+=item B<< $attr->install_accessors >>
+
+This method generates and installs code the attributes various
+accessors. It is typically called from the L<Class::MOP::Class>
+C<add_attribute> method.
+
+=item B<< $attr->remove_accessors >>
+
+This method removes all of the accessors associated with the
+attribute.
+
+This does not currently remove methods from the list returned by
+C<associated_methods>.
+
+=item B<< $attr->inline_get >>
+
+=item B<< $attr->inline_set >>
+
+=item B<< $attr->inline_has >>
+
+=item B<< $attr->inline_clear >>
+
+These methods return a code snippet suitable for inlining the relevant
+operation. They expect strings containing variable names to be used in the
+inlining, like C<'$self'> or C<'$_[1]'>.
+
+=back
+
+=head2 Introspection
+
+=over 4
+
+=item B<< Class::MOP::Attribute->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+It should also be noted that L<Class::MOP> will actually bootstrap
+this module by installing a number of attribute meta-objects into its
+metaclass.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Class.pm b/lib/Class/MOP/Class.pm
new file mode 100644
index 0000000..c5e1bae
--- /dev/null
+++ b/lib/Class/MOP/Class.pm
@@ -0,0 +1,2312 @@
+package Class::MOP::Class;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Class::MOP::Instance;
+use Class::MOP::Method::Wrapped;
+use Class::MOP::Method::Accessor;
+use Class::MOP::Method::Constructor;
+use Class::MOP::MiniTrait;
+
+use Carp 'confess';
+use Module::Runtime 'use_package_optimistically';
+use Scalar::Util 'blessed';
+use Sub::Name 'subname';
+use Try::Tiny;
+use List::Util 1.33 'all';
+
+use parent 'Class::MOP::Module',
+ 'Class::MOP::Mixin::HasAttributes',
+ 'Class::MOP::Mixin::HasMethods',
+ 'Class::MOP::Mixin::HasOverloads';
+
+# Creation
+
+sub initialize {
+ my $class = shift;
+
+ my $package_name;
+
+ if ( @_ % 2 ) {
+ $package_name = shift;
+ } else {
+ my %options = @_;
+ $package_name = $options{package};
+ }
+
+ ($package_name && !ref($package_name))
+ || ($class||__PACKAGE__)->_throw_exception( InitializeTakesUnBlessedPackageName => package_name => $package_name );
+ return Class::MOP::get_metaclass_by_name($package_name)
+ || $class->_construct_class_instance(package => $package_name, @_);
+}
+
+sub reinitialize {
+ my ( $class, @args ) = @_;
+ unshift @args, "package" if @args % 2;
+ my %options = @args;
+ my $old_metaclass = blessed($options{package})
+ ? $options{package}
+ : Class::MOP::get_metaclass_by_name($options{package});
+ $options{weaken} = Class::MOP::metaclass_is_weak($old_metaclass->name)
+ if !exists $options{weaken}
+ && blessed($old_metaclass)
+ && $old_metaclass->isa('Class::MOP::Class');
+ $old_metaclass->_remove_generated_metaobjects
+ if $old_metaclass && $old_metaclass->isa('Class::MOP::Class');
+ my $new_metaclass = $class->SUPER::reinitialize(%options);
+ $new_metaclass->_restore_metaobjects_from($old_metaclass)
+ if $old_metaclass && $old_metaclass->isa('Class::MOP::Class');
+ return $new_metaclass;
+}
+
+# NOTE: (meta-circularity)
+# this is a special form of _construct_instance
+# (see below), which is used to construct class
+# meta-object instances for any Class::MOP::*
+# class. All other classes will use the more
+# normal &construct_instance.
+sub _construct_class_instance {
+ my $class = shift;
+ my $options = @_ == 1 ? $_[0] : {@_};
+ my $package_name = $options->{package};
+ (defined $package_name && $package_name)
+ || $class->_throw_exception("ConstructClassInstanceTakesPackageName");
+ # NOTE:
+ # return the metaclass if we have it cached,
+ # and it is still defined (it has not been
+ # reaped by DESTROY yet, which can happen
+ # annoyingly enough during global destruction)
+
+ if (defined(my $meta = Class::MOP::get_metaclass_by_name($package_name))) {
+ return $meta;
+ }
+
+ $class
+ = ref $class
+ ? $class->_real_ref_name
+ : $class;
+
+ # now create the metaclass
+ my $meta;
+ if ($class eq 'Class::MOP::Class') {
+ $meta = $class->_new($options);
+ }
+ else {
+ # NOTE:
+ # it is safe to use meta here because
+ # class will always be a subclass of
+ # Class::MOP::Class, which defines meta
+ $meta = $class->meta->_construct_instance($options)
+ }
+
+ # and check the metaclass compatibility
+ $meta->_check_metaclass_compatibility();
+
+ Class::MOP::store_metaclass_by_name($package_name, $meta);
+
+ # NOTE:
+ # we need to weaken any anon classes
+ # so that they can call DESTROY properly
+ Class::MOP::weaken_metaclass($package_name) if $options->{weaken};
+
+ $meta;
+}
+
+sub _real_ref_name {
+ my $self = shift;
+
+ # NOTE: we need to deal with the possibility of class immutability here,
+ # and then get the name of the class appropriately
+ return $self->is_immutable
+ ? $self->_get_mutable_metaclass_name()
+ : ref $self;
+}
+
+sub _new {
+ my $class = shift;
+
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $options = @_ == 1 ? $_[0] : {@_};
+
+ return bless {
+ # inherited from Class::MOP::Package
+ 'package' => $options->{package},
+
+ # NOTE:
+ # since the following attributes will
+ # actually be loaded from the symbol
+ # table, and actually bypass the instance
+ # entirely, we can just leave these things
+ # listed here for reference, because they
+ # should not actually have a value associated
+ # with the slot.
+ 'namespace' => \undef,
+ 'methods' => {},
+
+ # inherited from Class::MOP::Module
+ 'version' => \undef,
+ 'authority' => \undef,
+
+ # defined in Class::MOP::Class
+ 'superclasses' => \undef,
+
+ 'attributes' => {},
+ 'attribute_metaclass' =>
+ ( $options->{'attribute_metaclass'} || 'Class::MOP::Attribute' ),
+ 'method_metaclass' =>
+ ( $options->{'method_metaclass'} || 'Class::MOP::Method' ),
+ 'wrapped_method_metaclass' => (
+ $options->{'wrapped_method_metaclass'}
+ || 'Class::MOP::Method::Wrapped'
+ ),
+ 'instance_metaclass' =>
+ ( $options->{'instance_metaclass'} || 'Class::MOP::Instance' ),
+ 'immutable_trait' => (
+ $options->{'immutable_trait'}
+ || 'Class::MOP::Class::Immutable::Trait'
+ ),
+ 'constructor_name' => ( $options->{constructor_name} || 'new' ),
+ 'constructor_class' => (
+ $options->{constructor_class} || 'Class::MOP::Method::Constructor'
+ ),
+ 'destructor_class' => $options->{destructor_class},
+ }, $class;
+}
+
+## Metaclass compatibility
+{
+ my %base_metaclass = (
+ attribute_metaclass => 'Class::MOP::Attribute',
+ method_metaclass => 'Class::MOP::Method',
+ wrapped_method_metaclass => 'Class::MOP::Method::Wrapped',
+ instance_metaclass => 'Class::MOP::Instance',
+ constructor_class => 'Class::MOP::Method::Constructor',
+ destructor_class => 'Class::MOP::Method::Destructor',
+ );
+
+ sub _base_metaclasses { %base_metaclass }
+}
+
+sub _check_metaclass_compatibility {
+ my $self = shift;
+
+ my @superclasses = $self->superclasses
+ or return;
+
+ $self->_fix_metaclass_incompatibility(@superclasses);
+
+ my %base_metaclass = $self->_base_metaclasses;
+
+ # this is always okay ...
+ return
+ if ref($self) eq 'Class::MOP::Class'
+ && all {
+ my $meta = $self->$_;
+ !defined($meta) || $meta eq $base_metaclass{$_};
+ }
+ keys %base_metaclass;
+
+ for my $superclass (@superclasses) {
+ $self->_check_class_metaclass_compatibility($superclass);
+ }
+
+ for my $metaclass_type ( keys %base_metaclass ) {
+ next unless defined $self->$metaclass_type;
+ for my $superclass (@superclasses) {
+ $self->_check_single_metaclass_compatibility( $metaclass_type,
+ $superclass );
+ }
+ }
+}
+
+sub _check_class_metaclass_compatibility {
+ my $self = shift;
+ my ( $superclass_name ) = @_;
+
+ if (!$self->_class_metaclass_is_compatible($superclass_name)) {
+ my $super_meta = Class::MOP::get_metaclass_by_name($superclass_name);
+
+ my $super_meta_type = $super_meta->_real_ref_name;
+
+ $self->_throw_exception( IncompatibleMetaclassOfSuperclass => class_name => $self->name,
+ class_meta_type => ref( $self ),
+ superclass_name => $superclass_name,
+ superclass_meta_type => $super_meta_type
+ );
+ }
+}
+
+sub _class_metaclass_is_compatible {
+ my $self = shift;
+ my ( $superclass_name ) = @_;
+
+ my $super_meta = Class::MOP::get_metaclass_by_name($superclass_name)
+ || return 1;
+
+ my $super_meta_name = $super_meta->_real_ref_name;
+
+ return $self->_is_compatible_with($super_meta_name);
+}
+
+sub _check_single_metaclass_compatibility {
+ my $self = shift;
+ my ( $metaclass_type, $superclass_name ) = @_;
+
+ if (!$self->_single_metaclass_is_compatible($metaclass_type, $superclass_name)) {
+ my $super_meta = Class::MOP::get_metaclass_by_name($superclass_name);
+
+ $self->_throw_exception( MetaclassTypeIncompatible => class_name => $self->name,
+ superclass_name => $superclass_name,
+ metaclass_type => $metaclass_type
+ );
+ }
+}
+
+sub _single_metaclass_is_compatible {
+ my $self = shift;
+ my ( $metaclass_type, $superclass_name ) = @_;
+
+ my $super_meta = Class::MOP::get_metaclass_by_name($superclass_name)
+ || return 1;
+
+ # for instance, Moose::Meta::Class has a error_class attribute, but
+ # Class::MOP::Class doesn't - this shouldn't be an error
+ return 1 unless $super_meta->can($metaclass_type);
+ # for instance, Moose::Meta::Class has a destructor_class, but
+ # Class::MOP::Class doesn't - this shouldn't be an error
+ return 1 unless defined $super_meta->$metaclass_type;
+ # if metaclass is defined in superclass but not here, it's not compatible
+ # this is a really odd case
+ return 0 unless defined $self->$metaclass_type;
+
+ return $self->$metaclass_type->_is_compatible_with($super_meta->$metaclass_type);
+}
+
+sub _fix_metaclass_incompatibility {
+ my $self = shift;
+ my @supers = map { Class::MOP::Class->initialize($_) } @_;
+
+ my $necessary = 0;
+ for my $super (@supers) {
+ $necessary = 1
+ if $self->_can_fix_metaclass_incompatibility($super);
+ }
+ return unless $necessary;
+
+ for my $super (@supers) {
+ if (!$self->_class_metaclass_is_compatible($super->name)) {
+ $self->_fix_class_metaclass_incompatibility($super);
+ }
+ }
+
+ my %base_metaclass = $self->_base_metaclasses;
+ for my $metaclass_type (keys %base_metaclass) {
+ for my $super (@supers) {
+ if (!$self->_single_metaclass_is_compatible($metaclass_type, $super->name)) {
+ $self->_fix_single_metaclass_incompatibility(
+ $metaclass_type, $super
+ );
+ }
+ }
+ }
+}
+
+sub _can_fix_metaclass_incompatibility {
+ my $self = shift;
+ my ($super_meta) = @_;
+
+ return 1 if $self->_class_metaclass_can_be_made_compatible($super_meta);
+
+ my %base_metaclass = $self->_base_metaclasses;
+ for my $metaclass_type (keys %base_metaclass) {
+ return 1 if $self->_single_metaclass_can_be_made_compatible($super_meta, $metaclass_type);
+ }
+
+ return;
+}
+
+sub _class_metaclass_can_be_made_compatible {
+ my $self = shift;
+ my ($super_meta) = @_;
+
+ return $self->_can_be_made_compatible_with($super_meta->_real_ref_name);
+}
+
+sub _single_metaclass_can_be_made_compatible {
+ my $self = shift;
+ my ($super_meta, $metaclass_type) = @_;
+
+ my $specific_meta = $self->$metaclass_type;
+
+ return unless $super_meta->can($metaclass_type);
+ my $super_specific_meta = $super_meta->$metaclass_type;
+
+ # for instance, Moose::Meta::Class has a destructor_class, but
+ # Class::MOP::Class doesn't - this shouldn't be an error
+ return unless defined $super_specific_meta;
+
+ # if metaclass is defined in superclass but not here, it's fixable
+ # this is a really odd case
+ return 1 unless defined $specific_meta;
+
+ return 1 if $specific_meta->_can_be_made_compatible_with($super_specific_meta);
+}
+
+sub _fix_class_metaclass_incompatibility {
+ my $self = shift;
+ my ( $super_meta ) = @_;
+
+ if ($self->_class_metaclass_can_be_made_compatible($super_meta)) {
+ ($self->is_pristine)
+ || $self->_throw_exception( CannotFixMetaclassCompatibility => class_name => $self->name,
+ superclass => $super_meta
+ );
+
+ my $super_meta_name = $super_meta->_real_ref_name;
+
+ $self->_make_compatible_with($super_meta_name);
+ }
+}
+
+sub _fix_single_metaclass_incompatibility {
+ my $self = shift;
+ my ( $metaclass_type, $super_meta ) = @_;
+
+ if ($self->_single_metaclass_can_be_made_compatible($super_meta, $metaclass_type)) {
+ ($self->is_pristine)
+ || $self->_throw_exception( CannotFixMetaclassCompatibility => class_name => $self->name,
+ superclass => $super_meta,
+ metaclass_type => $metaclass_type
+ );
+
+ my $new_metaclass = $self->$metaclass_type
+ ? $self->$metaclass_type->_get_compatible_metaclass($super_meta->$metaclass_type)
+ : $super_meta->$metaclass_type;
+ $self->{$metaclass_type} = $new_metaclass;
+ }
+}
+
+sub _restore_metaobjects_from {
+ my $self = shift;
+ my ($old_meta) = @_;
+
+ $self->_restore_metamethods_from($old_meta);
+ $self->_restore_metaattributes_from($old_meta);
+}
+
+sub _remove_generated_metaobjects {
+ my $self = shift;
+
+ for my $attr (map { $self->get_attribute($_) } $self->get_attribute_list) {
+ $attr->remove_accessors;
+ }
+}
+
+# creating classes with MOP ...
+
+sub create {
+ my $class = shift;
+ my @args = @_;
+
+ unshift @args, 'package' if @args % 2 == 1;
+ my %options = @args;
+
+ (ref $options{superclasses} eq 'ARRAY')
+ || __PACKAGE__->_throw_exception( CreateMOPClassTakesArrayRefOfSuperclasses => class => $class,
+ params => \%options
+ )
+ if exists $options{superclasses};
+
+ (ref $options{attributes} eq 'ARRAY')
+ || __PACKAGE__->_throw_exception( CreateMOPClassTakesArrayRefOfAttributes => class => $class,
+ params => \%options
+ )
+ if exists $options{attributes};
+
+ (ref $options{methods} eq 'HASH')
+ || __PACKAGE__->_throw_exception( CreateMOPClassTakesHashRefOfMethods => class => $class,
+ params => \%options
+ )
+ if exists $options{methods};
+
+ my $package = delete $options{package};
+ my $superclasses = delete $options{superclasses};
+ my $attributes = delete $options{attributes};
+ my $methods = delete $options{methods};
+ my $meta_name = exists $options{meta_name}
+ ? delete $options{meta_name}
+ : 'meta';
+
+ my $meta = $class->SUPER::create($package => %options);
+
+ $meta->_add_meta_method($meta_name)
+ if defined $meta_name;
+
+ $meta->superclasses(@{$superclasses})
+ if defined $superclasses;
+ # NOTE:
+ # process attributes first, so that they can
+ # install accessors, but locally defined methods
+ # can then overwrite them. It is maybe a little odd, but
+ # I think this should be the order of things.
+ if (defined $attributes) {
+ foreach my $attr (@{$attributes}) {
+ $meta->add_attribute($attr);
+ }
+ }
+ if (defined $methods) {
+ foreach my $method_name (keys %{$methods}) {
+ $meta->add_method($method_name, $methods->{$method_name});
+ }
+ }
+ return $meta;
+}
+
+# XXX: something more intelligent here?
+sub _anon_package_prefix { 'Class::MOP::Class::__ANON__::SERIAL::' }
+
+sub create_anon_class { shift->create_anon(@_) }
+sub is_anon_class { shift->is_anon(@_) }
+
+sub _anon_cache_key {
+ my $class = shift;
+ my %options = @_;
+ # Makes something like Super::Class|Super::Class::2
+ return join '=' => (
+ join( '|', sort @{ $options{superclasses} || [] } ),
+ );
+}
+
+# Instance Construction & Cloning
+
+sub new_object {
+ my $class = shift;
+
+ # NOTE:
+ # we need to protect the integrity of the
+ # Class::MOP::Class singletons here, so we
+ # delegate this to &construct_class_instance
+ # which will deal with the singletons
+ return $class->_construct_class_instance(@_)
+ if $class->name->isa('Class::MOP::Class');
+ return $class->_construct_instance(@_);
+}
+
+sub _construct_instance {
+ my $class = shift;
+ my $params = @_ == 1 ? $_[0] : {@_};
+ my $meta_instance = $class->get_meta_instance();
+ # FIXME:
+ # the code below is almost certainly incorrect
+ # but this is foreign inheritance, so we might
+ # have to kludge it in the end.
+ my $instance;
+ if (my $instance_class = blessed($params->{__INSTANCE__})) {
+ ($instance_class eq $class->name)
+ || $class->_throw_exception( InstanceBlessedIntoWrongClass => class_name => $class->name,
+ params => $params,
+ instance => $params->{__INSTANCE__}
+ );
+ $instance = $params->{__INSTANCE__};
+ }
+ elsif (exists $params->{__INSTANCE__}) {
+ $class->_throw_exception( InstanceMustBeABlessedReference => class_name => $class->name,
+ params => $params,
+ instance => $params->{__INSTANCE__}
+ );
+ }
+ else {
+ $instance = $meta_instance->create_instance();
+ }
+ foreach my $attr ($class->get_all_attributes()) {
+ $attr->initialize_instance_slot($meta_instance, $instance, $params);
+ }
+ if (Class::MOP::metaclass_is_weak($class->name)) {
+ $meta_instance->_set_mop_slot($instance, $class);
+ }
+ return $instance;
+}
+
+sub _inline_new_object {
+ my $self = shift;
+
+ return (
+ 'my $class = shift;',
+ '$class = Scalar::Util::blessed($class) || $class;',
+ $self->_inline_fallback_constructor('$class'),
+ $self->_inline_params('$params', '$class'),
+ $self->_inline_generate_instance('$instance', '$class'),
+ $self->_inline_slot_initializers,
+ $self->_inline_preserve_weak_metaclasses,
+ $self->_inline_extra_init,
+ 'return $instance',
+ );
+}
+
+sub _inline_fallback_constructor {
+ my $self = shift;
+ my ($class) = @_;
+ return (
+ 'return ' . $self->_generate_fallback_constructor($class),
+ 'if ' . $class . ' ne \'' . $self->name . '\';',
+ );
+}
+
+sub _generate_fallback_constructor {
+ my $self = shift;
+ my ($class) = @_;
+ return 'Class::MOP::Class->initialize(' . $class . ')->new_object(@_)',
+}
+
+sub _inline_params {
+ my $self = shift;
+ my ($params, $class) = @_;
+ return (
+ 'my ' . $params . ' = @_ == 1 ? $_[0] : {@_};',
+ );
+}
+
+sub _inline_generate_instance {
+ my $self = shift;
+ my ($inst, $class) = @_;
+ return (
+ 'my ' . $inst . ' = ' . $self->_inline_create_instance($class) . ';',
+ );
+}
+
+sub _inline_create_instance {
+ my $self = shift;
+
+ return $self->get_meta_instance->inline_create_instance(@_);
+}
+
+sub _inline_slot_initializers {
+ my $self = shift;
+
+ my $idx = 0;
+
+ return map { $self->_inline_slot_initializer($_, $idx++) }
+ sort { $a->name cmp $b->name } $self->get_all_attributes;
+}
+
+sub _inline_slot_initializer {
+ my $self = shift;
+ my ($attr, $idx) = @_;
+
+ if (defined(my $init_arg = $attr->init_arg)) {
+ my @source = (
+ 'if (exists $params->{\'' . $init_arg . '\'}) {',
+ $self->_inline_init_attr_from_constructor($attr, $idx),
+ '}',
+ );
+ if (my @default = $self->_inline_init_attr_from_default($attr, $idx)) {
+ push @source, (
+ 'else {',
+ @default,
+ '}',
+ );
+ }
+ return @source;
+ }
+ elsif (my @default = $self->_inline_init_attr_from_default($attr, $idx)) {
+ return (
+ '{',
+ @default,
+ '}',
+ );
+ }
+ else {
+ return ();
+ }
+}
+
+sub _inline_init_attr_from_constructor {
+ my $self = shift;
+ my ($attr, $idx) = @_;
+
+ my @initial_value = $attr->_inline_set_value(
+ '$instance', '$params->{\'' . $attr->init_arg . '\'}',
+ );
+
+ push @initial_value, (
+ '$attrs->[' . $idx . ']->set_initial_value(',
+ '$instance,',
+ $attr->_inline_instance_get('$instance'),
+ ');',
+ ) if $attr->has_initializer;
+
+ return @initial_value;
+}
+
+sub _inline_init_attr_from_default {
+ my $self = shift;
+ my ($attr, $idx) = @_;
+
+ my $default = $self->_inline_default_value($attr, $idx);
+ return unless $default;
+
+ my @initial_value = $attr->_inline_set_value('$instance', $default);
+
+ push @initial_value, (
+ '$attrs->[' . $idx . ']->set_initial_value(',
+ '$instance,',
+ $attr->_inline_instance_get('$instance'),
+ ');',
+ ) if $attr->has_initializer;
+
+ return @initial_value;
+}
+
+sub _inline_default_value {
+ my $self = shift;
+ my ($attr, $index) = @_;
+
+ if ($attr->has_default) {
+ # NOTE:
+ # default values can either be CODE refs
+ # in which case we need to call them. Or
+ # they can be scalars (strings/numbers)
+ # in which case we can just deal with them
+ # in the code we eval.
+ if ($attr->is_default_a_coderef) {
+ return '$defaults->[' . $index . ']->($instance)';
+ }
+ else {
+ return '$defaults->[' . $index . ']';
+ }
+ }
+ elsif ($attr->has_builder) {
+ return '$instance->' . $attr->builder;
+ }
+ else {
+ return;
+ }
+}
+
+sub _inline_preserve_weak_metaclasses {
+ my $self = shift;
+ if (Class::MOP::metaclass_is_weak($self->name)) {
+ return (
+ $self->_inline_set_mop_slot(
+ '$instance', 'Class::MOP::class_of($class)'
+ ) . ';'
+ );
+ }
+ else {
+ return ();
+ }
+}
+
+sub _inline_extra_init { }
+
+sub _eval_environment {
+ my $self = shift;
+
+ my @attrs = sort { $a->name cmp $b->name } $self->get_all_attributes;
+
+ my $defaults = [map { $_->default } @attrs];
+
+ return {
+ '$defaults' => \$defaults,
+ };
+}
+
+
+sub get_meta_instance {
+ my $self = shift;
+ $self->{'_meta_instance'} ||= $self->_create_meta_instance();
+}
+
+sub _create_meta_instance {
+ my $self = shift;
+
+ my $instance = $self->instance_metaclass->new(
+ associated_metaclass => $self,
+ attributes => [ $self->get_all_attributes() ],
+ );
+
+ $self->add_meta_instance_dependencies()
+ if $instance->is_dependent_on_superclasses();
+
+ return $instance;
+}
+
+# TODO: this is actually not being used!
+sub _inline_rebless_instance {
+ my $self = shift;
+
+ return $self->get_meta_instance->inline_rebless_instance_structure(@_);
+}
+
+sub _inline_get_mop_slot {
+ my $self = shift;
+
+ return $self->get_meta_instance->_inline_get_mop_slot(@_);
+}
+
+sub _inline_set_mop_slot {
+ my $self = shift;
+
+ return $self->get_meta_instance->_inline_set_mop_slot(@_);
+}
+
+sub _inline_clear_mop_slot {
+ my $self = shift;
+
+ return $self->get_meta_instance->_inline_clear_mop_slot(@_);
+}
+
+sub clone_object {
+ my $class = shift;
+ my $instance = shift;
+ (blessed($instance) && $instance->isa($class->name))
+ || $class->_throw_exception( CloneObjectExpectsAnInstanceOfMetaclass => class_name => $class->name,
+ instance => $instance,
+ );
+ # NOTE:
+ # we need to protect the integrity of the
+ # Class::MOP::Class singletons here, they
+ # should not be cloned.
+ return $instance if $instance->isa('Class::MOP::Class');
+ $class->_clone_instance($instance, @_);
+}
+
+sub _clone_instance {
+ my ($class, $instance, %params) = @_;
+ (blessed($instance))
+ || $class->_throw_exception( OnlyInstancesCanBeCloned => class_name => $class->name,
+ instance => $instance,
+ params => \%params
+ );
+ my $meta_instance = $class->get_meta_instance();
+ my $clone = $meta_instance->clone_instance($instance);
+ foreach my $attr ($class->get_all_attributes()) {
+ if ( defined( my $init_arg = $attr->init_arg ) ) {
+ if (exists $params{$init_arg}) {
+ $attr->set_value($clone, $params{$init_arg});
+ }
+ }
+ }
+ return $clone;
+}
+
+sub _force_rebless_instance {
+ my ($self, $instance, %params) = @_;
+ my $old_metaclass = Class::MOP::class_of($instance);
+
+ $old_metaclass->rebless_instance_away($instance, $self, %params)
+ if $old_metaclass;
+
+ my $meta_instance = $self->get_meta_instance;
+
+ if (Class::MOP::metaclass_is_weak($old_metaclass->name)) {
+ $meta_instance->_clear_mop_slot($instance);
+ }
+
+ # rebless!
+ # we use $_[1] here because of t/cmop/rebless_overload.t regressions
+ # on 5.8.8
+ $meta_instance->rebless_instance_structure($_[1], $self);
+
+ $self->_fixup_attributes_after_rebless($instance, $old_metaclass, %params);
+
+ if (Class::MOP::metaclass_is_weak($self->name)) {
+ $meta_instance->_set_mop_slot($instance, $self);
+ }
+}
+
+sub rebless_instance {
+ my ($self, $instance, %params) = @_;
+ my $old_metaclass = Class::MOP::class_of($instance);
+
+ my $old_class = $old_metaclass ? $old_metaclass->name : blessed($instance);
+ $self->name->isa($old_class)
+ || $self->_throw_exception( CanReblessOnlyIntoASubclass => class_name => $self->name,
+ instance => $instance,
+ instance_class => blessed( $instance ),
+ params => \%params,
+ );
+
+ $self->_force_rebless_instance($_[1], %params);
+
+ return $instance;
+}
+
+sub rebless_instance_back {
+ my ( $self, $instance ) = @_;
+ my $old_metaclass = Class::MOP::class_of($instance);
+ my $old_class
+ = $old_metaclass ? $old_metaclass->name : blessed($instance);
+ $old_class->isa( $self->name )
+ || $self->_throw_exception( CanReblessOnlyIntoASuperclass => class_name => $self->name,
+ instance => $instance,
+ instance_class => blessed( $instance ),
+ );
+
+ $self->_force_rebless_instance($_[1]);
+
+ return $instance;
+}
+
+sub rebless_instance_away {
+ # this intentionally does nothing, it is just a hook
+}
+
+sub _fixup_attributes_after_rebless {
+ my $self = shift;
+ my ($instance, $rebless_from, %params) = @_;
+ my $meta_instance = $self->get_meta_instance;
+
+ for my $attr ( $rebless_from->get_all_attributes ) {
+ next if $self->find_attribute_by_name( $attr->name );
+ $meta_instance->deinitialize_slot( $instance, $_ ) for $attr->slots;
+ }
+
+ foreach my $attr ( $self->get_all_attributes ) {
+ if ( $attr->has_value($instance) ) {
+ if ( defined( my $init_arg = $attr->init_arg ) ) {
+ $params{$init_arg} = $attr->get_value($instance)
+ unless exists $params{$init_arg};
+ }
+ else {
+ $attr->set_value($instance, $attr->get_value($instance));
+ }
+ }
+ }
+
+ foreach my $attr ($self->get_all_attributes) {
+ $attr->initialize_instance_slot($meta_instance, $instance, \%params);
+ }
+}
+
+sub _attach_attribute {
+ my ($self, $attribute) = @_;
+ $attribute->attach_to_class($self);
+}
+
+sub _post_add_attribute {
+ my ( $self, $attribute ) = @_;
+
+ $self->invalidate_meta_instances;
+
+ # invalidate package flag here
+ try {
+ local $SIG{__DIE__};
+ $attribute->install_accessors;
+ }
+ catch {
+ $self->remove_attribute( $attribute->name );
+ die $_;
+ };
+}
+
+sub remove_attribute {
+ my $self = shift;
+
+ my $removed_attribute = $self->SUPER::remove_attribute(@_)
+ or return;
+
+ $self->invalidate_meta_instances;
+
+ $removed_attribute->remove_accessors;
+ $removed_attribute->detach_from_class;
+
+ return$removed_attribute;
+}
+
+sub find_attribute_by_name {
+ my ( $self, $attr_name ) = @_;
+
+ foreach my $class ( $self->linearized_isa ) {
+ # fetch the meta-class ...
+ my $meta = Class::MOP::Class->initialize($class);
+ return $meta->get_attribute($attr_name)
+ if $meta->has_attribute($attr_name);
+ }
+
+ return;
+}
+
+sub get_all_attributes {
+ my $self = shift;
+ my %attrs = map { %{ Class::MOP::Class->initialize($_)->_attribute_map } }
+ reverse $self->linearized_isa;
+ return values %attrs;
+}
+
+# Inheritance
+
+sub superclasses {
+ my $self = shift;
+
+ my $isa = $self->get_or_add_package_symbol('@ISA');
+
+ if (@_) {
+ my @supers = @_;
+ @{$isa} = @supers;
+
+ # NOTE:
+ # on 5.8 and below, we need to call
+ # a method to get Perl to detect
+ # a cycle in the class hierarchy
+ my $class = $self->name;
+ $class->isa($class);
+
+ # NOTE:
+ # we need to check the metaclass
+ # compatibility here so that we can
+ # be sure that the superclass is
+ # not potentially creating an issues
+ # we don't know about
+
+ $self->_check_metaclass_compatibility();
+ $self->_superclasses_updated();
+ }
+
+ return @{$isa};
+}
+
+sub _superclasses_updated {
+ my $self = shift;
+ $self->update_meta_instance_dependencies();
+ # keep strong references to all our parents, so they don't disappear if
+ # they are anon classes and don't have any direct instances
+ $self->_superclass_metas(
+ map { Class::MOP::class_of($_) } $self->superclasses
+ );
+}
+
+sub _superclass_metas {
+ my $self = shift;
+ $self->{_superclass_metas} = [@_];
+}
+
+sub subclasses {
+ my $self = shift;
+ my $super_class = $self->name;
+
+ return @{ $super_class->mro::get_isarev() };
+}
+
+sub direct_subclasses {
+ my $self = shift;
+ my $super_class = $self->name;
+
+ return grep {
+ grep {
+ $_ eq $super_class
+ } Class::MOP::Class->initialize($_)->superclasses
+ } $self->subclasses;
+}
+
+sub linearized_isa {
+ return @{ mro::get_linear_isa( (shift)->name ) };
+}
+
+sub class_precedence_list {
+ my $self = shift;
+ my $name = $self->name;
+
+ unless (Class::MOP::IS_RUNNING_ON_5_10()) {
+ # NOTE:
+ # We need to check for circular inheritance here
+ # if we are not on 5.10, cause 5.8 detects it late.
+ # This will do nothing if all is well, and blow up
+ # otherwise. Yes, it's an ugly hack, better
+ # suggestions are welcome.
+ # - SL
+ ($name || return)->isa('This is a test for circular inheritance')
+ }
+
+ # if our mro is c3, we can
+ # just grab the linear_isa
+ if (mro::get_mro($name) eq 'c3') {
+ return @{ mro::get_linear_isa($name) }
+ }
+ else {
+ # NOTE:
+ # we can't grab the linear_isa for dfs
+ # since it has all the duplicates
+ # already removed.
+ return (
+ $name,
+ map {
+ Class::MOP::Class->initialize($_)->class_precedence_list()
+ } $self->superclasses()
+ );
+ }
+}
+
+sub _method_lookup_order {
+ return (shift->linearized_isa, 'UNIVERSAL');
+}
+
+## Methods
+
+{
+ my $fetch_and_prepare_method = sub {
+ my ($self, $method_name) = @_;
+ my $wrapped_metaclass = $self->wrapped_method_metaclass;
+ # fetch it locally
+ my $method = $self->get_method($method_name);
+ # if we don't have local ...
+ unless ($method) {
+ # try to find the next method
+ $method = $self->find_next_method_by_name($method_name);
+ # die if it does not exist
+ (defined $method)
+ || $self->_throw_exception( MethodNameNotFoundInInheritanceHierarchy => class_name => $self->name,
+ method_name => $method_name
+ );
+ # and now make sure to wrap it
+ # even if it is already wrapped
+ # because we need a new sub ref
+ $method = $wrapped_metaclass->wrap($method,
+ package_name => $self->name,
+ name => $method_name,
+ );
+ }
+ else {
+ # now make sure we wrap it properly
+ $method = $wrapped_metaclass->wrap($method,
+ package_name => $self->name,
+ name => $method_name,
+ ) unless $method->isa($wrapped_metaclass);
+ }
+ $self->add_method($method_name => $method);
+ return $method;
+ };
+
+ sub add_before_method_modifier {
+ my ($self, $method_name, $method_modifier) = @_;
+ (defined $method_name && length $method_name)
+ || $self->_throw_exception( MethodModifierNeedsMethodName => class_name => $self->name );
+ my $method = $fetch_and_prepare_method->($self, $method_name);
+ $method->add_before_modifier(
+ subname(':before' => $method_modifier)
+ );
+ }
+
+ sub add_after_method_modifier {
+ my ($self, $method_name, $method_modifier) = @_;
+ (defined $method_name && length $method_name)
+ || $self->_throw_exception( MethodModifierNeedsMethodName => class_name => $self->name );
+ my $method = $fetch_and_prepare_method->($self, $method_name);
+ $method->add_after_modifier(
+ subname(':after' => $method_modifier)
+ );
+ }
+
+ sub add_around_method_modifier {
+ my ($self, $method_name, $method_modifier) = @_;
+ (defined $method_name && length $method_name)
+ || $self->_throw_exception( MethodModifierNeedsMethodName => class_name => $self->name );
+ my $method = $fetch_and_prepare_method->($self, $method_name);
+ $method->add_around_modifier(
+ subname(':around' => $method_modifier)
+ );
+ }
+
+ # NOTE:
+ # the methods above used to be named like this:
+ # ${pkg}::${method}:(before|after|around)
+ # but this proved problematic when using one modifier
+ # to wrap multiple methods (something which is likely
+ # to happen pretty regularly IMO). So instead of naming
+ # it like this, I have chosen to just name them purely
+ # with their modifier names, like so:
+ # :(before|after|around)
+ # The fact is that in a stack trace, it will be fairly
+ # evident from the context what method they are attached
+ # to, and so don't need the fully qualified name.
+}
+
+sub find_method_by_name {
+ my ($self, $method_name) = @_;
+ (defined $method_name && length $method_name)
+ || $self->_throw_exception( MethodNameNotGiven => class_name => $self->name );
+ foreach my $class ($self->_method_lookup_order) {
+ my $method = Class::MOP::Class->initialize($class)->get_method($method_name);
+ return $method if defined $method;
+ }
+ return;
+}
+
+sub get_all_methods {
+ my $self = shift;
+
+ my %methods;
+ for my $class ( reverse $self->_method_lookup_order ) {
+ my $meta = Class::MOP::Class->initialize($class);
+
+ $methods{ $_->name } = $_ for $meta->_get_local_methods;
+ }
+
+ return values %methods;
+}
+
+sub get_all_method_names {
+ my $self = shift;
+ map { $_->name } $self->get_all_methods;
+}
+
+sub find_all_methods_by_name {
+ my ($self, $method_name) = @_;
+ (defined $method_name && length $method_name)
+ || $self->_throw_exception( MethodNameNotGiven => class_name => $self->name );
+ my @methods;
+ foreach my $class ($self->_method_lookup_order) {
+ # fetch the meta-class ...
+ my $meta = Class::MOP::Class->initialize($class);
+ push @methods => {
+ name => $method_name,
+ class => $class,
+ code => $meta->get_method($method_name)
+ } if $meta->has_method($method_name);
+ }
+ return @methods;
+}
+
+sub find_next_method_by_name {
+ my ($self, $method_name) = @_;
+ (defined $method_name && length $method_name)
+ || $self->_throw_exception( MethodNameNotGiven => class_name => $self->name );
+ my @cpl = ($self->_method_lookup_order);
+ shift @cpl; # discard ourselves
+ foreach my $class (@cpl) {
+ my $method = Class::MOP::Class->initialize($class)->get_method($method_name);
+ return $method if defined $method;
+ }
+ return;
+}
+
+sub update_meta_instance_dependencies {
+ my $self = shift;
+
+ if ( $self->{meta_instance_dependencies} ) {
+ return $self->add_meta_instance_dependencies;
+ }
+}
+
+sub add_meta_instance_dependencies {
+ my $self = shift;
+
+ $self->remove_meta_instance_dependencies;
+
+ my @attrs = $self->get_all_attributes();
+
+ my %seen;
+ my @classes = grep { not $seen{ $_->name }++ }
+ map { $_->associated_class } @attrs;
+
+ foreach my $class (@classes) {
+ $class->add_dependent_meta_instance($self);
+ }
+
+ $self->{meta_instance_dependencies} = \@classes;
+}
+
+sub remove_meta_instance_dependencies {
+ my $self = shift;
+
+ if ( my $classes = delete $self->{meta_instance_dependencies} ) {
+ foreach my $class (@$classes) {
+ $class->remove_dependent_meta_instance($self);
+ }
+
+ return $classes;
+ }
+
+ return;
+
+}
+
+sub add_dependent_meta_instance {
+ my ( $self, $metaclass ) = @_;
+ push @{ $self->{dependent_meta_instances} }, $metaclass;
+}
+
+sub remove_dependent_meta_instance {
+ my ( $self, $metaclass ) = @_;
+ my $name = $metaclass->name;
+ @$_ = grep { $_->name ne $name } @$_
+ for $self->{dependent_meta_instances};
+}
+
+sub invalidate_meta_instances {
+ my $self = shift;
+ $_->invalidate_meta_instance()
+ for $self, @{ $self->{dependent_meta_instances} };
+}
+
+sub invalidate_meta_instance {
+ my $self = shift;
+ undef $self->{_meta_instance};
+}
+
+# check if we can reinitialize
+sub is_pristine {
+ my $self = shift;
+
+ # if any local attr is defined
+ return if $self->get_attribute_list;
+
+ # or any non-declared methods
+ for my $method ( map { $self->get_method($_) } $self->get_method_list ) {
+ return if $method->isa("Class::MOP::Method::Generated");
+ # FIXME do we need to enforce this too? return unless $method->isa( $self->method_metaclass );
+ }
+
+ return 1;
+}
+
+## Class closing
+
+sub is_mutable { 1 }
+sub is_immutable { 0 }
+
+sub immutable_options { %{ $_[0]{__immutable}{options} || {} } }
+
+sub _immutable_options {
+ my ( $self, @args ) = @_;
+
+ return (
+ inline_accessors => 1,
+ inline_constructor => 1,
+ inline_destructor => 0,
+ debug => 0,
+ immutable_trait => $self->immutable_trait,
+ constructor_name => $self->constructor_name,
+ constructor_class => $self->constructor_class,
+ destructor_class => $self->destructor_class,
+ @args,
+ );
+}
+
+sub make_immutable {
+ my ( $self, @args ) = @_;
+
+ return $self unless $self->is_mutable;
+
+ my ($file, $line) = (caller)[1..2];
+
+ $self->_initialize_immutable(
+ file => $file,
+ line => $line,
+ $self->_immutable_options(@args),
+ );
+ $self->_rebless_as_immutable(@args);
+
+ return $self;
+}
+
+sub make_mutable {
+ my $self = shift;
+
+ if ( $self->is_immutable ) {
+ my @args = $self->immutable_options;
+ $self->_rebless_as_mutable();
+ $self->_remove_inlined_code(@args);
+ delete $self->{__immutable};
+ return $self;
+ }
+ else {
+ return;
+ }
+}
+
+sub _rebless_as_immutable {
+ my ( $self, @args ) = @_;
+
+ $self->{__immutable}{original_class} = ref $self;
+
+ bless $self => $self->_immutable_metaclass(@args);
+}
+
+sub _immutable_metaclass {
+ my ( $self, %args ) = @_;
+
+ if ( my $class = $args{immutable_metaclass} ) {
+ return $class;
+ }
+
+ my $trait = $args{immutable_trait} = $self->immutable_trait
+ || $self->_throw_exception( NoImmutableTraitSpecifiedForClass => class_name => $self->name,
+ params => \%args
+ );
+
+ my $meta = $self->meta;
+ my $meta_attr = $meta->find_attribute_by_name("immutable_trait");
+
+ my $class_name;
+
+ if ( $meta_attr and $trait eq $meta_attr->default ) {
+ # if the trait is the same as the default we try and pick a
+ # predictable name for the immutable metaclass
+ $class_name = 'Class::MOP::Class::Immutable::' . ref($self);
+ }
+ else {
+ $class_name = join '::', 'Class::MOP::Class::Immutable::CustomTrait',
+ $trait, 'ForMetaClass', ref($self);
+ }
+
+ return $class_name
+ if Class::MOP::does_metaclass_exist($class_name);
+
+ # If the metaclass is a subclass of CMOP::Class which has had
+ # metaclass roles applied (via Moose), then we want to make sure
+ # that we preserve that anonymous class (see Fey::ORM for an
+ # example of where this matters).
+ my $meta_name = $meta->_real_ref_name;
+
+ my $immutable_meta = $meta_name->create(
+ $class_name,
+ superclasses => [ ref $self ],
+ );
+
+ Class::MOP::MiniTrait::apply( $immutable_meta, $trait );
+
+ $immutable_meta->make_immutable(
+ inline_constructor => 0,
+ inline_accessors => 0,
+ );
+
+ return $class_name;
+}
+
+sub _remove_inlined_code {
+ my $self = shift;
+
+ $self->remove_method( $_->name ) for $self->_inlined_methods;
+
+ delete $self->{__immutable}{inlined_methods};
+}
+
+sub _inlined_methods { @{ $_[0]{__immutable}{inlined_methods} || [] } }
+
+sub _add_inlined_method {
+ my ( $self, $method ) = @_;
+
+ push @{ $self->{__immutable}{inlined_methods} ||= [] }, $method;
+}
+
+sub _initialize_immutable {
+ my ( $self, %args ) = @_;
+
+ $self->{__immutable}{options} = \%args;
+ $self->_install_inlined_code(%args);
+}
+
+sub _install_inlined_code {
+ my ( $self, %args ) = @_;
+
+ # FIXME
+ $self->_inline_accessors(%args) if $args{inline_accessors};
+ $self->_inline_constructor(%args) if $args{inline_constructor};
+ $self->_inline_destructor(%args) if $args{inline_destructor};
+}
+
+sub _rebless_as_mutable {
+ my $self = shift;
+
+ bless $self, $self->_get_mutable_metaclass_name;
+
+ return $self;
+}
+
+sub _inline_accessors {
+ my $self = shift;
+
+ foreach my $attr_name ( $self->get_attribute_list ) {
+ $self->get_attribute($attr_name)->install_accessors(1);
+ }
+}
+
+sub _inline_constructor {
+ my ( $self, %args ) = @_;
+
+ my $name = $args{constructor_name};
+ # A class may not even have a constructor, and that's okay.
+ return unless defined $name;
+
+ if ( $self->has_method($name) && !$args{replace_constructor} ) {
+ my $class = $self->name;
+ warn "Not inlining a constructor for $class since it defines"
+ . " its own constructor.\n"
+ . "If you are certain you don't need to inline your"
+ . " constructor, specify inline_constructor => 0 in your"
+ . " call to $class->meta->make_immutable\n";
+ return;
+ }
+
+ my $constructor_class = $args{constructor_class};
+
+ {
+ local $@;
+ use_package_optimistically($constructor_class);
+ }
+
+ my $constructor = $constructor_class->new(
+ options => \%args,
+ metaclass => $self,
+ is_inline => 1,
+ package_name => $self->name,
+ name => $name,
+ definition_context => {
+ description => "constructor " . $self->name . "::" . $name,
+ file => $args{file},
+ line => $args{line},
+ },
+ );
+
+ if ( $args{replace_constructor} or $constructor->can_be_inlined ) {
+ $self->add_method( $name => $constructor );
+ $self->_add_inlined_method($constructor);
+ }
+}
+
+sub _inline_destructor {
+ my ( $self, %args ) = @_;
+
+ ( exists $args{destructor_class} && defined $args{destructor_class} )
+ || $self->_throw_exception( NoDestructorClassSpecified => class_name => $self->name,
+ params => \%args,
+ );
+
+ if ( $self->has_method('DESTROY') && ! $args{replace_destructor} ) {
+ my $class = $self->name;
+ warn "Not inlining a destructor for $class since it defines"
+ . " its own destructor.\n";
+ return;
+ }
+
+ my $destructor_class = $args{destructor_class};
+
+ {
+ local $@;
+ use_package_optimistically($destructor_class);
+ }
+
+ return unless $destructor_class->is_needed($self);
+
+ my $destructor = $destructor_class->new(
+ options => \%args,
+ metaclass => $self,
+ package_name => $self->name,
+ name => 'DESTROY',
+ definition_context => {
+ description => "destructor " . $self->name . "::DESTROY",
+ file => $args{file},
+ line => $args{line},
+ },
+ );
+
+ if ( $args{replace_destructor} or $destructor->can_be_inlined ) {
+ $self->add_method( 'DESTROY' => $destructor );
+ $self->_add_inlined_method($destructor);
+ }
+}
+
+1;
+
+# ABSTRACT: Class Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Class - Class Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 SYNOPSIS
+
+ # assuming that class Foo
+ # has been defined, you can
+
+ # use this for introspection ...
+
+ # add a method to Foo ...
+ Foo->meta->add_method( 'bar' => sub {...} )
+
+ # get a list of all the classes searched
+ # the method dispatcher in the correct order
+ Foo->meta->class_precedence_list()
+
+ # remove a method from Foo
+ Foo->meta->remove_method('bar');
+
+ # or use this to actually create classes ...
+
+ Class::MOP::Class->create(
+ 'Bar' => (
+ version => '0.01',
+ superclasses => ['Foo'],
+ attributes => [
+ Class::MOP::Attribute->new('$bar'),
+ Class::MOP::Attribute->new('$baz'),
+ ],
+ methods => {
+ calculate_bar => sub {...},
+ construct_baz => sub {...}
+ }
+ )
+ );
+
+=head1 DESCRIPTION
+
+The Class Protocol is the largest and most complex part of the
+Class::MOP meta-object protocol. It controls the introspection and
+manipulation of Perl 5 classes, and it can create them as well. The
+best way to understand what this module can do is to read the
+documentation for each of its methods.
+
+=head1 INHERITANCE
+
+C<Class::MOP::Class> is a subclass of L<Class::MOP::Module>.
+
+=head1 METHODS
+
+=head2 Class construction
+
+These methods all create new C<Class::MOP::Class> objects. These
+objects can represent existing classes or they can be used to create
+new classes from scratch.
+
+The metaclass object for a given class is a singleton. If you attempt
+to create a metaclass for the same class twice, you will just get the
+existing object.
+
+=over 4
+
+=item B<< Class::MOP::Class->create($package_name, %options) >>
+
+This method creates a new C<Class::MOP::Class> object with the given
+package name. It accepts a number of options:
+
+=over 8
+
+=item * version
+
+An optional version number for the newly created package.
+
+=item * authority
+
+An optional authority for the newly created package.
+See L<Class::MOP::Module/authority> for more details.
+
+=item * superclasses
+
+An optional array reference of superclass names.
+
+=item * methods
+
+An optional hash reference of methods for the class. The keys of the
+hash reference are method names and values are subroutine references.
+
+=item * attributes
+
+An optional array reference of L<Class::MOP::Attribute> objects.
+
+=item * meta_name
+
+Specifies the name to install the C<meta> method for this class under.
+If it is not passed, C<meta> is assumed, and if C<undef> is explicitly
+given, no meta method will be installed.
+
+=item * weaken
+
+If true, the metaclass that is stored in the global cache will be a
+weak reference.
+
+Classes created in this way are destroyed once the metaclass they are
+attached to goes out of scope, and will be removed from Perl's internal
+symbol table.
+
+All instances of a class with a weakened metaclass keep a special
+reference to the metaclass object, which prevents the metaclass from
+going out of scope while any instances exist.
+
+This only works if the instance is based on a hash reference, however.
+
+=back
+
+=item B<< Class::MOP::Class->create_anon_class(%options) >>
+
+This method works just like C<< Class::MOP::Class->create >> but it
+creates an "anonymous" class. In fact, the class does have a name, but
+that name is a unique name generated internally by this module.
+
+It accepts the same C<superclasses>, C<methods>, and C<attributes>
+parameters that C<create> accepts.
+
+It also accepts a C<cache> option. If this is C<true>, then the anonymous class
+will be cached based on its superclasses and roles. If an existing anonymous
+class in the cache has the same superclasses and roles, it will be reused.
+
+Anonymous classes default to C<< weaken => 1 >> if cache is C<false>, although
+this can be overridden.
+
+=item B<< Class::MOP::Class->initialize($package_name, %options) >>
+
+This method will initialize a C<Class::MOP::Class> object for the
+named package. Unlike C<create>, this method I<will not> create a new
+class.
+
+The purpose of this method is to retrieve a C<Class::MOP::Class>
+object for introspecting an existing class.
+
+If an existing C<Class::MOP::Class> object exists for the named
+package, it will be returned, and any options provided will be
+ignored!
+
+If the object does not yet exist, it will be created.
+
+The valid options that can be passed to this method are
+C<attribute_metaclass>, C<method_metaclass>,
+C<wrapped_method_metaclass>, and C<instance_metaclass>. These are all
+optional, and default to the appropriate class in the C<Class::MOP>
+distribution.
+
+=back
+
+=head2 Object instance construction and cloning
+
+These methods are all related to creating and/or cloning object
+instances.
+
+=over 4
+
+=item B<< $metaclass->clone_object($instance, %params) >>
+
+This method clones an existing object instance. Any parameters you
+provide are will override existing attribute values in the object.
+
+This is a convenience method for cloning an object instance, then
+blessing it into the appropriate package.
+
+You could implement a clone method in your class, using this method:
+
+ sub clone {
+ my ($self, %params) = @_;
+ $self->meta->clone_object($self, %params);
+ }
+
+=item B<< $metaclass->rebless_instance($instance, %params) >>
+
+This method changes the class of C<$instance> to the metaclass's class.
+
+You can only rebless an instance into a subclass of its current
+class. If you pass any additional parameters, these will be treated
+like constructor parameters and used to initialize the object's
+attributes. Any existing attributes that are already set will be
+overwritten.
+
+Before reblessing the instance, this method will call
+C<rebless_instance_away> on the instance's current metaclass. This method
+will be passed the instance, the new metaclass, and any parameters
+specified to C<rebless_instance>. By default, C<rebless_instance_away>
+does nothing; it is merely a hook.
+
+=item B<< $metaclass->rebless_instance_back($instance) >>
+
+Does the same thing as C<rebless_instance>, except that you can only
+rebless an instance into one of its superclasses. Any attributes that
+do not exist in the superclass will be deinitialized.
+
+This is a much more dangerous operation than C<rebless_instance>,
+especially when multiple inheritance is involved, so use this carefully!
+
+=item B<< $metaclass->new_object(%params) >>
+
+This method is used to create a new object of the metaclass's
+class. Any parameters you provide are used to initialize the
+instance's attributes. A special C<__INSTANCE__> key can be passed to
+provide an already generated instance, rather than having Class::MOP
+generate it for you. This is mostly useful for using Class::MOP with
+foreign classes which generate instances using their own constructors.
+
+=item B<< $metaclass->instance_metaclass >>
+
+Returns the class name of the instance metaclass. See
+L<Class::MOP::Instance> for more information on the instance
+metaclass.
+
+=item B<< $metaclass->get_meta_instance >>
+
+Returns an instance of the C<instance_metaclass> to be used in the
+construction of a new instance of the class.
+
+=back
+
+=head2 Informational predicates
+
+These are a few predicate methods for asking information about the
+class itself.
+
+=over 4
+
+=item B<< $metaclass->is_anon_class >>
+
+This returns true if the class was created by calling C<<
+Class::MOP::Class->create_anon_class >>.
+
+=item B<< $metaclass->is_mutable >>
+
+This returns true if the class is still mutable.
+
+=item B<< $metaclass->is_immutable >>
+
+This returns true if the class has been made immutable.
+
+=item B<< $metaclass->is_pristine >>
+
+A class is I<not> pristine if it has non-inherited attributes or if it
+has any generated methods.
+
+=back
+
+=head2 Inheritance Relationships
+
+=over 4
+
+=item B<< $metaclass->superclasses(@superclasses) >>
+
+This is a read-write accessor which represents the superclass
+relationships of the metaclass's class.
+
+This is basically sugar around getting and setting C<@ISA>.
+
+=item B<< $metaclass->class_precedence_list >>
+
+This returns a list of all of the class's ancestor classes. The
+classes are returned in method dispatch order.
+
+=item B<< $metaclass->linearized_isa >>
+
+This returns a list based on C<class_precedence_list> but with all
+duplicates removed.
+
+=item B<< $metaclass->subclasses >>
+
+This returns a list of all subclasses for this class, even indirect
+subclasses.
+
+=item B<< $metaclass->direct_subclasses >>
+
+This returns a list of immediate subclasses for this class, which does not
+include indirect subclasses.
+
+=back
+
+=head2 Method introspection and creation
+
+These methods allow you to introspect a class's methods, as well as
+add, remove, or change methods.
+
+Determining what is truly a method in a Perl 5 class requires some
+heuristics (aka guessing).
+
+Methods defined outside the package with a fully qualified name (C<sub
+Package::name { ... }>) will be included. Similarly, methods named
+with a fully qualified name using L<Sub::Name> are also included.
+
+However, we attempt to ignore imported functions.
+
+Ultimately, we are using heuristics to determine what truly is a
+method in a class, and these heuristics may get the wrong answer in
+some edge cases. However, for most "normal" cases the heuristics work
+correctly.
+
+=over 4
+
+=item B<< $metaclass->get_method($method_name) >>
+
+This will return a L<Class::MOP::Method> for the specified
+C<$method_name>. If the class does not have the specified method, it
+returns C<undef>
+
+=item B<< $metaclass->has_method($method_name) >>
+
+Returns a boolean indicating whether or not the class defines the
+named method. It does not include methods inherited from parent
+classes.
+
+=item B<< $metaclass->get_method_list >>
+
+This will return a list of method I<names> for all methods defined in
+this class.
+
+=item B<< $metaclass->add_method($method_name, $method) >>
+
+This method takes a method name and a subroutine reference, and adds
+the method to the class.
+
+The subroutine reference can be a L<Class::MOP::Method>, and you are
+strongly encouraged to pass a meta method object instead of a code
+reference. If you do so, that object gets stored as part of the
+class's method map directly. If not, the meta information will have to
+be recreated later, and may be incorrect.
+
+If you provide a method object, this method will clone that object if
+the object's package name does not match the class name. This lets us
+track the original source of any methods added from other classes
+(notably Moose roles).
+
+=item B<< $metaclass->remove_method($method_name) >>
+
+Remove the named method from the class. This method returns the
+L<Class::MOP::Method> object for the method.
+
+=item B<< $metaclass->method_metaclass >>
+
+Returns the class name of the method metaclass, see
+L<Class::MOP::Method> for more information on the method metaclass.
+
+=item B<< $metaclass->wrapped_method_metaclass >>
+
+Returns the class name of the wrapped method metaclass, see
+L<Class::MOP::Method::Wrapped> for more information on the wrapped
+method metaclass.
+
+=item B<< $metaclass->get_all_methods >>
+
+This will traverse the inheritance hierarchy and return a list of all
+the L<Class::MOP::Method> objects for this class and its parents.
+
+=item B<< $metaclass->find_method_by_name($method_name) >>
+
+This will return a L<Class::MOP::Method> for the specified
+C<$method_name>. If the class does not have the specified method, it
+returns C<undef>
+
+Unlike C<get_method>, this method I<will> look for the named method in
+superclasses.
+
+=item B<< $metaclass->get_all_method_names >>
+
+This will return a list of method I<names> for all of this class's
+methods, including inherited methods.
+
+=item B<< $metaclass->find_all_methods_by_name($method_name) >>
+
+This method looks for the named method in the class and all of its
+parents. It returns every matching method it finds in the inheritance
+tree, so it returns a list of methods.
+
+Each method is returned as a hash reference with three keys. The keys
+are C<name>, C<class>, and C<code>. The C<code> key has a
+L<Class::MOP::Method> object as its value.
+
+The list of methods is distinct.
+
+=item B<< $metaclass->find_next_method_by_name($method_name) >>
+
+This method returns the first method in any superclass matching the
+given name. It is effectively the method that C<SUPER::$method_name>
+would dispatch to.
+
+=back
+
+=head2 Attribute introspection and creation
+
+Because Perl 5 does not have a core concept of attributes in classes,
+we can only return information about attributes which have been added
+via this class's methods. We cannot discover information about
+attributes which are defined in terms of "regular" Perl 5 methods.
+
+=over 4
+
+=item B<< $metaclass->get_attribute($attribute_name) >>
+
+This will return a L<Class::MOP::Attribute> for the specified
+C<$attribute_name>. If the class does not have the specified
+attribute, it returns C<undef>.
+
+NOTE that get_attribute does not search superclasses, for that you
+need to use C<find_attribute_by_name>.
+
+=item B<< $metaclass->has_attribute($attribute_name) >>
+
+Returns a boolean indicating whether or not the class defines the
+named attribute. It does not include attributes inherited from parent
+classes.
+
+=item B<< $metaclass->get_attribute_list >>
+
+This will return a list of attributes I<names> for all attributes
+defined in this class. Note that this operates on the current class
+only, it does not traverse the inheritance hierarchy.
+
+=item B<< $metaclass->get_all_attributes >>
+
+This will traverse the inheritance hierarchy and return a list of all
+the L<Class::MOP::Attribute> objects for this class and its parents.
+
+=item B<< $metaclass->find_attribute_by_name($attribute_name) >>
+
+This will return a L<Class::MOP::Attribute> for the specified
+C<$attribute_name>. If the class does not have the specified
+attribute, it returns C<undef>.
+
+Unlike C<get_attribute>, this attribute I<will> look for the named
+attribute in superclasses.
+
+=item B<< $metaclass->add_attribute(...) >>
+
+This method accepts either an existing L<Class::MOP::Attribute>
+object or parameters suitable for passing to that class's C<new>
+method.
+
+The attribute provided will be added to the class.
+
+Any accessor methods defined by the attribute will be added to the
+class when the attribute is added.
+
+If an attribute of the same name already exists, the old attribute
+will be removed first.
+
+=item B<< $metaclass->remove_attribute($attribute_name) >>
+
+This will remove the named attribute from the class, and
+L<Class::MOP::Attribute> object.
+
+Removing an attribute also removes any accessor methods defined by the
+attribute.
+
+However, note that removing an attribute will only affect I<future>
+object instances created for this class, not existing instances.
+
+=item B<< $metaclass->attribute_metaclass >>
+
+Returns the class name of the attribute metaclass for this class. By
+default, this is L<Class::MOP::Attribute>.
+
+=back
+
+=head2 Overload introspection and creation
+
+These methods provide an API to the core L<overload> functionality.
+
+=over 4
+
+=item B<< $metaclass->is_overloaded >>
+
+Returns true if overloading is enabled for this class. Corresponds to
+L<overload::Overloaded|overload/Public Functions>.
+
+=item B<< $metaclass->get_overloaded_operator($op) >>
+
+Returns the L<Class::MOP::Overload> object corresponding to the operator named
+C<$op>, if one exists for this class.
+
+=item B<< $metaclass->has_overloaded_operator($op) >>
+
+Returns whether or not the operator C<$op> is overloaded for this class.
+
+=item B<< $metaclass->get_overload_list >>
+
+Returns a list of operator names which have been overloaded (see
+L<overload/Overloadable Operations> for the list of valid operator names).
+
+=item B<< $metaclass->get_all_overloaded_operators >>
+
+Returns a list of L<Class::MOP::Overload> objects corresponding to the
+operators that have been overloaded.
+
+=item B<< $metaclass->add_overloaded_operator($op, $impl) >>
+
+Overloads the operator C<$op> for this class. The C<$impl> can be a coderef, a
+method name, or a L<Class::MOP::Overload> object. Corresponds to
+C<< use overload $op => $impl; >>
+
+=item B<< $metaclass->remove_overloaded_operator($op) >>
+
+Remove overloading for operator C<$op>. Corresponds to C<< no overload $op; >>
+
+=item B<< $metaclass->get_overload_fallback_value >>
+
+Returns the overload C<fallback> setting for the package.
+
+=item B<< $metaclass->set_overload_fallback_value($fallback) >>
+
+Sets the overload C<fallback> setting for the package.
+
+=back
+
+=head2 Class Immutability
+
+Making a class immutable "freezes" the class definition. You can no
+longer call methods which alter the class, such as adding or removing
+methods or attributes.
+
+Making a class immutable lets us optimize the class by inlining some
+methods, and also allows us to optimize some methods on the metaclass
+object itself.
+
+After immutabilization, the metaclass object will cache most informational
+methods that returns information about methods or attributes. Methods which
+would alter the class, such as C<add_attribute> and C<add_method>, will
+throw an error on an immutable metaclass object.
+
+The immutabilization system in L<Moose> takes much greater advantage
+of the inlining features than Class::MOP itself does.
+
+=over 4
+
+=item B<< $metaclass->make_immutable(%options) >>
+
+This method will create an immutable transformer and use it to make
+the class and its metaclass object immutable, and returns true
+(you should not rely on the details of this value apart from its truth).
+
+This method accepts the following options:
+
+=over 8
+
+=item * inline_accessors
+
+=item * inline_constructor
+
+=item * inline_destructor
+
+These are all booleans indicating whether the specified method(s)
+should be inlined.
+
+By default, accessors and the constructor are inlined, but not the
+destructor.
+
+=item * immutable_trait
+
+The name of a class which will be used as a parent class for the
+metaclass object being made immutable. This "trait" implements the
+post-immutability functionality of the metaclass (but not the
+transformation itself).
+
+This defaults to L<Class::MOP::Class::Immutable::Trait>.
+
+=item * constructor_name
+
+This is the constructor method name. This defaults to "new".
+
+=item * constructor_class
+
+The name of the method metaclass for constructors. It will be used to
+generate the inlined constructor. This defaults to
+"Class::MOP::Method::Constructor".
+
+=item * replace_constructor
+
+This is a boolean indicating whether an existing constructor should be
+replaced when inlining a constructor. This defaults to false.
+
+=item * destructor_class
+
+The name of the method metaclass for destructors. It will be used to
+generate the inlined destructor. This defaults to
+"Class::MOP::Method::Denstructor".
+
+=item * replace_destructor
+
+This is a boolean indicating whether an existing destructor should be
+replaced when inlining a destructor. This defaults to false.
+
+=back
+
+=item B<< $metaclass->immutable_options >>
+
+Returns a hash of the options used when making the class immutable, including
+both defaults and anything supplied by the user in the call to C<<
+$metaclass->make_immutable >>. This is useful if you need to temporarily make
+a class mutable and then restore immutability as it was before.
+
+=item B<< $metaclass->make_mutable >>
+
+Calling this method reverse the immutabilization transformation.
+
+=back
+
+=head2 Method Modifiers
+
+Method modifiers are hooks which allow a method to be wrapped with
+I<before>, I<after> and I<around> method modifiers. Every time a
+method is called, its modifiers are also called.
+
+A class can modify its own methods, as well as methods defined in
+parent classes.
+
+=head3 How method modifiers work?
+
+Method modifiers work by wrapping the original method and then
+replacing it in the class's symbol table. The wrappers will handle
+calling all the modifiers in the appropriate order and preserving the
+calling context for the original method.
+
+The return values of C<before> and C<after> modifiers are
+ignored. This is because their purpose is B<not> to filter the input
+and output of the primary method (this is done with an I<around>
+modifier).
+
+This may seem like an odd restriction to some, but doing this allows
+for simple code to be added at the beginning or end of a method call
+without altering the function of the wrapped method or placing any
+extra responsibility on the code of the modifier.
+
+Of course if you have more complex needs, you can use the C<around>
+modifier which allows you to change both the parameters passed to the
+wrapped method, as well as its return value.
+
+Before and around modifiers are called in last-defined-first-called
+order, while after modifiers are called in first-defined-first-called
+order. So the call tree might looks something like this:
+
+ before 2
+ before 1
+ around 2
+ around 1
+ primary
+ around 1
+ around 2
+ after 1
+ after 2
+
+=head3 What is the performance impact?
+
+Of course there is a performance cost associated with method
+modifiers, but we have made every effort to make that cost directly
+proportional to the number of modifier features you use.
+
+The wrapping method does its best to B<only> do as much work as it
+absolutely needs to. In order to do this we have moved some of the
+performance costs to set-up time, where they are easier to amortize.
+
+All this said, our benchmarks have indicated the following:
+
+ simple wrapper with no modifiers 100% slower
+ simple wrapper with simple before modifier 400% slower
+ simple wrapper with simple after modifier 450% slower
+ simple wrapper with simple around modifier 500-550% slower
+ simple wrapper with all 3 modifiers 1100% slower
+
+These numbers may seem daunting, but you must remember, every feature
+comes with some cost. To put things in perspective, just doing a
+simple C<AUTOLOAD> which does nothing but extract the name of the
+method called and return it costs about 400% over a normal method
+call.
+
+=over 4
+
+=item B<< $metaclass->add_before_method_modifier($method_name, $code) >>
+
+This wraps the specified method with the supplied subroutine
+reference. The modifier will be called as a method itself, and will
+receive the same arguments as are passed to the method.
+
+When the modifier exits, the wrapped method will be called.
+
+The return value of the modifier will be ignored.
+
+=item B<< $metaclass->add_after_method_modifier($method_name, $code) >>
+
+This wraps the specified method with the supplied subroutine
+reference. The modifier will be called as a method itself, and will
+receive the same arguments as are passed to the method.
+
+When the wrapped methods exits, the modifier will be called.
+
+The return value of the modifier will be ignored.
+
+=item B<< $metaclass->add_around_method_modifier($method_name, $code) >>
+
+This wraps the specified method with the supplied subroutine
+reference.
+
+The first argument passed to the modifier will be a subroutine
+reference to the wrapped method. The second argument is the object,
+and after that come any arguments passed when the method is called.
+
+The around modifier can choose to call the original method, as well as
+what arguments to pass if it does so.
+
+The return value of the modifier is what will be seen by the caller.
+
+=back
+
+=head2 Introspection
+
+=over 4
+
+=item B<< Class::MOP::Class->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+It should also be noted that L<Class::MOP> will actually bootstrap
+this module by installing a number of attribute meta-objects into its
+metaclass.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Class/Immutable/Trait.pm b/lib/Class/MOP/Class/Immutable/Trait.pm
new file mode 100644
index 0000000..8bb6c93
--- /dev/null
+++ b/lib/Class/MOP/Class/Immutable/Trait.pm
@@ -0,0 +1,172 @@
+package Class::MOP::Class::Immutable::Trait;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use MRO::Compat;
+use Module::Runtime 'use_module';
+
+# the original class of the metaclass instance
+sub _get_mutable_metaclass_name { $_[0]{__immutable}{original_class} }
+
+sub is_mutable { 0 }
+sub is_immutable { 1 }
+
+sub _immutable_metaclass { ref $_[1] }
+
+sub _immutable_read_only {
+ my $name = shift;
+ __throw_exception( CallingReadOnlyMethodOnAnImmutableInstance => method_name => $name );
+}
+
+sub _immutable_cannot_call {
+ my $name = shift;
+ __throw_exception( CallingMethodOnAnImmutableInstance => method_name => $name );
+}
+
+for my $name (qw/superclasses/) {
+ no strict 'refs';
+ *{__PACKAGE__."::$name"} = sub {
+ my $orig = shift;
+ my $self = shift;
+ _immutable_read_only($name) if @_;
+ $self->$orig;
+ };
+}
+
+for my $name (qw/add_method alias_method remove_method add_attribute remove_attribute remove_package_symbol add_package_symbol/) {
+ no strict 'refs';
+ *{__PACKAGE__."::$name"} = sub { _immutable_cannot_call($name) };
+}
+
+sub class_precedence_list {
+ my $orig = shift;
+ my $self = shift;
+ @{ $self->{__immutable}{class_precedence_list}
+ ||= [ $self->$orig ] };
+}
+
+sub linearized_isa {
+ my $orig = shift;
+ my $self = shift;
+ @{ $self->{__immutable}{linearized_isa} ||= [ $self->$orig ] };
+}
+
+sub get_all_methods {
+ my $orig = shift;
+ my $self = shift;
+ @{ $self->{__immutable}{get_all_methods} ||= [ $self->$orig ] };
+}
+
+sub get_all_method_names {
+ my $orig = shift;
+ my $self = shift;
+ @{ $self->{__immutable}{get_all_method_names} ||= [ $self->$orig ] };
+}
+
+sub get_all_attributes {
+ my $orig = shift;
+ my $self = shift;
+ @{ $self->{__immutable}{get_all_attributes} ||= [ $self->$orig ] };
+}
+
+sub get_meta_instance {
+ my $orig = shift;
+ my $self = shift;
+ $self->{__immutable}{get_meta_instance} ||= $self->$orig;
+}
+
+sub _method_map {
+ my $orig = shift;
+ my $self = shift;
+ $self->{__immutable}{_method_map} ||= $self->$orig;
+}
+
+# private method, for this file only -
+# if we declare a method here, it will behave differently depending on what
+# class this trait is applied to, so we won't have a reliable parameter list.
+sub __throw_exception {
+ my ($exception_type, @args_to_exception) = @_;
+ die use_module( "Moose::Exception::$exception_type" )->new( @args_to_exception );
+}
+
+1;
+
+# ABSTRACT: Implements immutability for metaclass objects
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Class::Immutable::Trait - Implements immutability for metaclass objects
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class provides a pseudo-trait that is applied to immutable metaclass
+objects. In reality, it is simply a parent class.
+
+It implements caching and read-only-ness for various metaclass methods.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Deprecated.pm b/lib/Class/MOP/Deprecated.pm
new file mode 100644
index 0000000..cb9329a
--- /dev/null
+++ b/lib/Class/MOP/Deprecated.pm
@@ -0,0 +1,95 @@
+package Class::MOP::Deprecated;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Package::DeprecationManager -deprecations => {
+ 'Class::Load wrapper functions' => '2.1100',
+};
+
+1;
+
+# ABSTRACT: Manages deprecation warnings for Class::MOP
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Deprecated - Manages deprecation warnings for Class::MOP
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+ use Class::MOP::Deprecated -api_version => $version;
+
+=head1 FUNCTIONS
+
+This module manages deprecation warnings for features that have been
+deprecated in Class::MOP.
+
+If you specify C<< -api_version => $version >>, you can use deprecated features
+without warnings. Note that this special treatment is limited to the package
+that loads C<Class::MOP::Deprecated>.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Instance.pm b/lib/Class/MOP/Instance.pm
new file mode 100644
index 0000000..3cffb4e
--- /dev/null
+++ b/lib/Class/MOP/Instance.pm
@@ -0,0 +1,533 @@
+package Class::MOP::Instance;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'isweak', 'weaken', 'blessed';
+
+use parent 'Class::MOP::Object';
+
+# make this not a valid method name, to avoid (most) attribute conflicts
+my $RESERVED_MOP_SLOT = '<<MOP>>';
+
+sub BUILDARGS {
+ my ($class, @args) = @_;
+
+ if ( @args == 1 ) {
+ unshift @args, "associated_metaclass";
+ } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
+ # compat mode
+ my ( $meta, @attrs ) = @args;
+ @args = ( associated_metaclass => $meta, attributes => \@attrs );
+ }
+
+ my %options = @args;
+ # FIXME lazy_build
+ $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
+ $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
+
+ return \%options;
+}
+
+sub new {
+ my $class = shift;
+ my $options = $class->BUILDARGS(@_);
+
+ # FIXME replace with a proper constructor
+ my $instance = $class->_new(%$options);
+
+ # FIXME weak_ref => 1,
+ weaken($instance->{'associated_metaclass'});
+
+ return $instance;
+}
+
+sub _new {
+ my $class = shift;
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+ return bless {
+ # NOTE:
+ # I am not sure that it makes
+ # sense to pass in the meta
+ # The ideal would be to just
+ # pass in the class name, but
+ # that is placing too much of
+ # an assumption on bless(),
+ # which is *probably* a safe
+ # assumption,.. but you can
+ # never tell <:)
+ 'associated_metaclass' => $params->{associated_metaclass},
+ 'attributes' => $params->{attributes},
+ 'slots' => $params->{slots},
+ 'slot_hash' => $params->{slot_hash},
+ } => $class;
+}
+
+sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
+
+sub create_instance {
+ my $self = shift;
+ bless {}, $self->_class_name;
+}
+
+sub clone_instance {
+ my ($self, $instance) = @_;
+
+ my $clone = $self->create_instance;
+ for my $attr ($self->get_all_attributes) {
+ next unless $attr->has_value($instance);
+ for my $slot ($attr->slots) {
+ my $val = $self->get_slot_value($instance, $slot);
+ $self->set_slot_value($clone, $slot, $val);
+ $self->weaken_slot_value($clone, $slot)
+ if $self->slot_value_is_weak($instance, $slot);
+ }
+ }
+
+ $self->_set_mop_slot($clone, $self->_get_mop_slot($instance))
+ if $self->_has_mop_slot($instance);
+
+ return $clone;
+}
+
+# operations on meta instance
+
+sub get_all_slots {
+ my $self = shift;
+ return @{$self->{'slots'}};
+}
+
+sub get_all_attributes {
+ my $self = shift;
+ return @{$self->{attributes}};
+}
+
+sub is_valid_slot {
+ my ($self, $slot_name) = @_;
+ exists $self->{'slot_hash'}->{$slot_name};
+}
+
+# operations on created instances
+
+sub get_slot_value {
+ my ($self, $instance, $slot_name) = @_;
+ $instance->{$slot_name};
+}
+
+sub set_slot_value {
+ my ($self, $instance, $slot_name, $value) = @_;
+ $instance->{$slot_name} = $value;
+}
+
+sub initialize_slot {
+ my ($self, $instance, $slot_name) = @_;
+ return;
+}
+
+sub deinitialize_slot {
+ my ( $self, $instance, $slot_name ) = @_;
+ delete $instance->{$slot_name};
+}
+
+sub initialize_all_slots {
+ my ($self, $instance) = @_;
+ foreach my $slot_name ($self->get_all_slots) {
+ $self->initialize_slot($instance, $slot_name);
+ }
+}
+
+sub deinitialize_all_slots {
+ my ($self, $instance) = @_;
+ foreach my $slot_name ($self->get_all_slots) {
+ $self->deinitialize_slot($instance, $slot_name);
+ }
+}
+
+sub is_slot_initialized {
+ my ($self, $instance, $slot_name, $value) = @_;
+ exists $instance->{$slot_name};
+}
+
+sub weaken_slot_value {
+ my ($self, $instance, $slot_name) = @_;
+ weaken $instance->{$slot_name};
+}
+
+sub slot_value_is_weak {
+ my ($self, $instance, $slot_name) = @_;
+ isweak $instance->{$slot_name};
+}
+
+sub strengthen_slot_value {
+ my ($self, $instance, $slot_name) = @_;
+ $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
+}
+
+sub rebless_instance_structure {
+ my ($self, $instance, $metaclass) = @_;
+
+ # we use $_[1] here because of t/cmop/rebless_overload.t regressions
+ # on 5.8.8
+ bless $_[1], $metaclass->name;
+}
+
+sub is_dependent_on_superclasses {
+ return; # for meta instances that require updates on inherited slot changes
+}
+
+sub _get_mop_slot {
+ my ($self, $instance) = @_;
+ $self->get_slot_value($instance, $RESERVED_MOP_SLOT);
+}
+
+sub _has_mop_slot {
+ my ($self, $instance) = @_;
+ $self->is_slot_initialized($instance, $RESERVED_MOP_SLOT);
+}
+
+sub _set_mop_slot {
+ my ($self, $instance, $value) = @_;
+ $self->set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
+}
+
+sub _clear_mop_slot {
+ my ($self, $instance) = @_;
+ $self->deinitialize_slot($instance, $RESERVED_MOP_SLOT);
+}
+
+# inlinable operation snippets
+
+sub is_inlinable { 1 }
+
+sub inline_create_instance {
+ my ($self, $class_variable) = @_;
+ 'bless {} => ' . $class_variable;
+}
+
+sub inline_slot_access {
+ my ($self, $instance, $slot_name) = @_;
+ sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
+}
+
+sub inline_get_is_lvalue { 1 }
+
+sub inline_get_slot_value {
+ my ($self, $instance, $slot_name) = @_;
+ $self->inline_slot_access($instance, $slot_name);
+}
+
+sub inline_set_slot_value {
+ my ($self, $instance, $slot_name, $value) = @_;
+ $self->inline_slot_access($instance, $slot_name) . " = $value",
+}
+
+sub inline_initialize_slot {
+ my ($self, $instance, $slot_name) = @_;
+ return '';
+}
+
+sub inline_deinitialize_slot {
+ my ($self, $instance, $slot_name) = @_;
+ "delete " . $self->inline_slot_access($instance, $slot_name);
+}
+sub inline_is_slot_initialized {
+ my ($self, $instance, $slot_name) = @_;
+ "exists " . $self->inline_slot_access($instance, $slot_name);
+}
+
+sub inline_weaken_slot_value {
+ my ($self, $instance, $slot_name) = @_;
+ sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
+}
+
+sub inline_strengthen_slot_value {
+ my ($self, $instance, $slot_name) = @_;
+ $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
+}
+
+sub inline_rebless_instance_structure {
+ my ($self, $instance, $class_variable) = @_;
+ "bless $instance => $class_variable";
+}
+
+sub _inline_get_mop_slot {
+ my ($self, $instance) = @_;
+ $self->inline_get_slot_value($instance, $RESERVED_MOP_SLOT);
+}
+
+sub _inline_set_mop_slot {
+ my ($self, $instance, $value) = @_;
+ $self->inline_set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
+}
+
+sub _inline_clear_mop_slot {
+ my ($self, $instance) = @_;
+ $self->inline_deinitialize_slot($instance, $RESERVED_MOP_SLOT);
+}
+
+1;
+
+# ABSTRACT: Instance Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Instance - Instance Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+The Instance Protocol controls the creation of object instances, and
+the storage of attribute values in those instances.
+
+Using this API directly in your own code violates encapsulation, and
+we recommend that you use the appropriate APIs in L<Class::MOP::Class>
+and L<Class::MOP::Attribute> instead. Those APIs in turn call the
+methods in this class as appropriate.
+
+This class also participates in generating inlined code by providing
+snippets of code to access an object instance.
+
+=head1 METHODS
+
+=head2 Object construction
+
+=over 4
+
+=item B<< Class::MOP::Instance->new(%options) >>
+
+This method creates a new meta-instance object.
+
+It accepts the following keys in C<%options>:
+
+=over 8
+
+=item * associated_metaclass
+
+The L<Class::MOP::Class> object for which instances will be created.
+
+=item * attributes
+
+An array reference of L<Class::MOP::Attribute> objects. These are the
+attributes which can be stored in each instance.
+
+=back
+
+=back
+
+=head2 Creating and altering instances
+
+=over 4
+
+=item B<< $metainstance->create_instance >>
+
+This method returns a reference blessed into the associated
+metaclass's class.
+
+The default is to use a hash reference. Subclasses can override this.
+
+=item B<< $metainstance->clone_instance($instance) >>
+
+Given an instance, this method creates a new object by making
+I<shallow> clone of the original.
+
+=back
+
+=head2 Introspection
+
+=over 4
+
+=item B<< $metainstance->associated_metaclass >>
+
+This returns the L<Class::MOP::Class> object associated with the
+meta-instance object.
+
+=item B<< $metainstance->get_all_slots >>
+
+This returns a list of slot names stored in object instances. In
+almost all cases, slot names correspond directly attribute names.
+
+=item B<< $metainstance->is_valid_slot($slot_name) >>
+
+This will return true if C<$slot_name> is a valid slot name.
+
+=item B<< $metainstance->get_all_attributes >>
+
+This returns a list of attributes corresponding to the attributes
+passed to the constructor.
+
+=back
+
+=head2 Operations on Instance Structures
+
+It's important to understand that the meta-instance object is a
+different entity from the actual instances it creates. For this
+reason, any operations on the C<$instance_structure> always require
+that the object instance be passed to the method.
+
+=over 4
+
+=item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
+
+=item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->initialize_all_slots($instance_structure) >>
+
+=item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
+
+=item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->slot_value_is_weak($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
+
+=item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
+
+The exact details of what each method does should be fairly obvious
+from the method name.
+
+=back
+
+=head2 Inlinable Instance Operations
+
+=over 4
+
+=item B<< $metainstance->is_inlinable >>
+
+This is a boolean that indicates whether or not slot access operations
+can be inlined. By default it is true, but subclasses can override
+this.
+
+=item B<< $metainstance->inline_create_instance($class_variable) >>
+
+This method expects a string that, I<when inlined>, will become a
+class name. This would literally be something like C<'$class'>, not an
+actual class name.
+
+It returns a snippet of code that creates a new object for the
+class. This is something like C< bless {}, $class_name >.
+
+=item B<< $metainstance->inline_get_is_lvalue >>
+
+Returns whether or not C<inline_get_slot_value> is a valid lvalue. This can be
+used to do extra optimizations when generating inlined methods.
+
+=item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
+
+=item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
+
+=item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
+
+=item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
+
+=item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
+
+=item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
+
+=item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
+
+=item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
+
+These methods all expect two arguments. The first is the name of a
+variable, than when inlined, will represent the object
+instance. Typically this will be a literal string like C<'$_[0]'>.
+
+The second argument is a slot name.
+
+The method returns a snippet of code that, when inlined, performs some
+operation on the instance.
+
+=item B<< $metainstance->inline_rebless_instance_structure($instance_variable, $class_variable) >>
+
+This takes the name of a variable that will, when inlined, represent the object
+instance, and the name of a variable that will represent the class to rebless
+into, and returns code to rebless an instance into a class.
+
+=back
+
+=head2 Introspection
+
+=over 4
+
+=item B<< Class::MOP::Instance->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+It should also be noted that L<Class::MOP> will actually bootstrap
+this module by installing a number of attribute meta-objects into its
+metaclass.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method.pm b/lib/Class/MOP/Method.pm
new file mode 100644
index 0000000..d945bcb
--- /dev/null
+++ b/lib/Class/MOP/Method.pm
@@ -0,0 +1,343 @@
+package Class::MOP::Method;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'weaken', 'reftype', 'blessed';
+
+use parent 'Class::MOP::Object';
+
+# NOTE:
+# if poked in the right way,
+# they should act like CODE refs.
+use overload '&{}' => sub { $_[0]->body }, fallback => 1;
+
+# construction
+
+sub wrap {
+ my ( $class, @args ) = @_;
+
+ unshift @args, 'body' if @args % 2 == 1;
+
+ my %params = @args;
+ my $code = $params{body};
+
+ if (blessed($code) && $code->isa(__PACKAGE__)) {
+ my $method = $code->clone;
+ delete $params{body};
+ Class::MOP::class_of($class)->rebless_instance($method, %params);
+ return $method;
+ }
+ elsif (!ref $code || 'CODE' ne reftype($code)) {
+ $class->_throw_exception( WrapTakesACodeRefToBless => params => \%params,
+ class => $class,
+ code => $code
+ );
+ }
+
+ ($params{package_name} && $params{name})
+ || $class->_throw_exception( PackageNameAndNameParamsNotGivenToWrap => params => \%params,
+ class => $class,
+ code => $code
+ );
+
+ my $self = $class->_new(\%params);
+
+ weaken($self->{associated_metaclass}) if $self->{associated_metaclass};
+
+ return $self;
+}
+
+sub _new {
+ my $class = shift;
+
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+
+ return bless {
+ 'body' => $params->{body},
+ 'associated_metaclass' => $params->{associated_metaclass},
+ 'package_name' => $params->{package_name},
+ 'name' => $params->{name},
+ 'original_method' => $params->{original_method},
+ } => $class;
+}
+
+## accessors
+
+sub associated_metaclass { shift->{'associated_metaclass'} }
+
+sub attach_to_class {
+ my ( $self, $class ) = @_;
+ $self->{associated_metaclass} = $class;
+ weaken($self->{associated_metaclass});
+}
+
+sub detach_from_class {
+ my $self = shift;
+ delete $self->{associated_metaclass};
+}
+
+sub fully_qualified_name {
+ my $self = shift;
+ $self->package_name . '::' . $self->name;
+}
+
+sub original_method { (shift)->{'original_method'} }
+
+sub _set_original_method { $_[0]->{'original_method'} = $_[1] }
+
+# It's possible that this could cause a loop if there is a circular
+# reference in here. That shouldn't ever happen in normal
+# circumstances, since original method only gets set when clone is
+# called. We _could_ check for such a loop, but it'd involve some sort
+# of package-lexical variable, and wouldn't be terribly subclassable.
+sub original_package_name {
+ my $self = shift;
+
+ $self->original_method
+ ? $self->original_method->original_package_name
+ : $self->package_name;
+}
+
+sub original_name {
+ my $self = shift;
+
+ $self->original_method
+ ? $self->original_method->original_name
+ : $self->name;
+}
+
+sub original_fully_qualified_name {
+ my $self = shift;
+
+ $self->original_method
+ ? $self->original_method->original_fully_qualified_name
+ : $self->fully_qualified_name;
+}
+
+sub execute {
+ my $self = shift;
+ $self->body->(@_);
+}
+
+# We used to go through use Class::MOP::Class->clone_instance to do this, but
+# this was awfully slow. This method may be called a number of times when
+# classes are loaded (especially during Moose role application), so it is
+# worth optimizing. - DR
+sub clone {
+ my $self = shift;
+
+ my $clone = bless { %{$self}, @_ }, blessed($self);
+ weaken($clone->{associated_metaclass}) if $clone->{associated_metaclass};
+
+ $clone->_set_original_method($self);
+
+ return $clone;
+}
+
+1;
+
+# ABSTRACT: Method Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method - Method Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+The Method Protocol is very small, since methods in Perl 5 are just
+subroutines in a specific package. We provide a very basic
+introspection interface.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Method->wrap($code, %options) >>
+
+This is the constructor. It accepts a method body in the form of
+either a code reference or a L<Class::MOP::Method> instance, followed
+by a hash of options.
+
+The options are:
+
+=over 8
+
+=item * name
+
+The method name (without a package name). This is required if C<$code>
+is a coderef.
+
+=item * package_name
+
+The package name for the method. This is required if C<$code> is a
+coderef.
+
+=item * associated_metaclass
+
+An optional L<Class::MOP::Class> object. This is the metaclass for the
+method's class.
+
+=back
+
+=item B<< $metamethod->clone(%params) >>
+
+This makes a shallow clone of the method object. In particular,
+subroutine reference itself is shared between all clones of a given
+method.
+
+When a method is cloned, the original method object will be available
+by calling C<original_method> on the clone.
+
+=item B<< $metamethod->body >>
+
+This returns a reference to the method's subroutine.
+
+=item B<< $metamethod->name >>
+
+This returns the method's name.
+
+=item B<< $metamethod->package_name >>
+
+This returns the method's package name.
+
+=item B<< $metamethod->fully_qualified_name >>
+
+This returns the method's fully qualified name (package name and
+method name).
+
+=item B<< $metamethod->associated_metaclass >>
+
+This returns the L<Class::MOP::Class> object for the method, if one
+exists.
+
+=item B<< $metamethod->original_method >>
+
+If this method object was created as a clone of some other method
+object, this returns the object that was cloned.
+
+=item B<< $metamethod->original_name >>
+
+This returns the method's original name, wherever it was first
+defined.
+
+If this method is a clone of a clone (of a clone, etc.), this method
+returns the name from the I<first> method in the chain of clones.
+
+=item B<< $metamethod->original_package_name >>
+
+This returns the method's original package name, wherever it was first
+defined.
+
+If this method is a clone of a clone (of a clone, etc.), this method
+returns the package name from the I<first> method in the chain of
+clones.
+
+=item B<< $metamethod->original_fully_qualified_name >>
+
+This returns the method's original fully qualified name, wherever it
+was first defined.
+
+If this method is a clone of a clone (of a clone, etc.), this method
+returns the fully qualified name from the I<first> method in the chain
+of clones.
+
+=item B<< $metamethod->is_stub >>
+
+Returns true if the method is just a stub:
+
+ sub foo;
+
+=item B<< $metamethod->attach_to_class($metaclass) >>
+
+Given a L<Class::MOP::Class> object, this method sets the associated
+metaclass for the method. This will overwrite any existing associated
+metaclass.
+
+=item B<< $metamethod->detach_from_class >>
+
+Removes any associated metaclass object for the method.
+
+=item B<< $metamethod->execute(...) >>
+
+This executes the method. Any arguments provided will be passed on to
+the method itself.
+
+=item B<< Class::MOP::Method->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+It should also be noted that L<Class::MOP> will actually bootstrap
+this module by installing a number of attribute meta-objects into its
+metaclass.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method/Accessor.pm b/lib/Class/MOP/Method/Accessor.pm
new file mode 100644
index 0000000..673bfde
--- /dev/null
+++ b/lib/Class/MOP/Method/Accessor.pm
@@ -0,0 +1,409 @@
+package Class::MOP::Method::Accessor;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed', 'weaken';
+use Try::Tiny;
+
+use parent 'Class::MOP::Method::Generated';
+
+sub new {
+ my $class = shift;
+ my %options = @_;
+
+ (exists $options{attribute})
+ || $class->_throw_exception( MustSupplyAnAttributeToConstructWith => params => \%options,
+ class => $class,
+ );
+
+ (exists $options{accessor_type})
+ || $class->_throw_exception( MustSupplyAnAccessorTypeToConstructWith => params => \%options,
+ class => $class,
+ );
+
+ (blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
+ || $class->_throw_exception( MustSupplyAClassMOPAttributeInstance => params => \%options,
+ class => $class
+ );
+
+ ($options{package_name} && $options{name})
+ || $class->_throw_exception( MustSupplyPackageNameAndName => params => \%options,
+ class => $class
+ );
+
+ my $self = $class->_new(\%options);
+
+ # we don't want this creating
+ # a cycle in the code, if not
+ # needed
+ weaken($self->{'attribute'});
+
+ $self->_initialize_body;
+
+ return $self;
+}
+
+sub _new {
+ my $class = shift;
+
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+
+ return bless {
+ # inherited from Class::MOP::Method
+ body => $params->{body},
+ associated_metaclass => $params->{associated_metaclass},
+ package_name => $params->{package_name},
+ name => $params->{name},
+ original_method => $params->{original_method},
+
+ # inherit from Class::MOP::Generated
+ is_inline => $params->{is_inline} || 0,
+ definition_context => $params->{definition_context},
+
+ # defined in this class
+ attribute => $params->{attribute},
+ accessor_type => $params->{accessor_type},
+ } => $class;
+}
+
+## accessors
+
+sub associated_attribute { (shift)->{'attribute'} }
+sub accessor_type { (shift)->{'accessor_type'} }
+
+## factory
+
+sub _initialize_body {
+ my $self = shift;
+
+ my $method_name = join "_" => (
+ '_generate',
+ $self->accessor_type,
+ 'method',
+ ($self->is_inline ? 'inline' : ())
+ );
+
+ $self->{'body'} = $self->$method_name();
+}
+
+## generators
+
+sub _generate_accessor_method {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return sub {
+ if (@_ >= 2) {
+ $attr->set_value($_[0], $_[1]);
+ }
+ $attr->get_value($_[0]);
+ };
+}
+
+sub _generate_accessor_method_inline {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return try {
+ $self->_compile_code([
+ 'sub {',
+ 'if (@_ > 1) {',
+ $attr->_inline_set_value('$_[0]', '$_[1]'),
+ '}',
+ $attr->_inline_get_value('$_[0]'),
+ '}',
+ ]);
+ }
+ catch {
+ $self->_throw_exception( CouldNotGenerateInlineAttributeMethod => instance => $self,
+ error => $_,
+ option => "accessor"
+ );
+ };
+}
+
+sub _generate_reader_method {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+ my $class = $attr->associated_class;
+
+ return sub {
+ $self->_throw_exception( CannotAssignValueToReadOnlyAccessor => class_name => $class->name,
+ value => $_[1],
+ attribute => $attr
+ )
+ if @_ > 1;
+ $attr->get_value($_[0]);
+ };
+}
+
+sub _generate_reader_method_inline {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+ my $attr_name = $attr->name;
+
+ return try {
+ $self->_compile_code([
+ 'sub {',
+ 'if (@_ > 1) {',
+ $self->_inline_throw_exception( CannotAssignValueToReadOnlyAccessor =>
+ 'class_name => ref $_[0],'.
+ 'value => $_[1],'.
+ "attribute_name => '".$attr_name."'",
+ ) . ';',
+ '}',
+ $attr->_inline_get_value('$_[0]'),
+ '}',
+ ]);
+ }
+ catch {
+ $self->_throw_exception( CouldNotGenerateInlineAttributeMethod => instance => $self,
+ error => $_,
+ option => "reader"
+ );
+ };
+}
+
+sub _inline_throw_exception {
+ my ( $self, $exception_type, $throw_args ) = @_;
+ return 'die Module::Runtime::use_module("Moose::Exception::' . $exception_type . '")->new(' . ($throw_args || '') . ')';
+}
+
+sub _generate_writer_method {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return sub {
+ $attr->set_value($_[0], $_[1]);
+ };
+}
+
+sub _generate_writer_method_inline {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return try {
+ $self->_compile_code([
+ 'sub {',
+ $attr->_inline_set_value('$_[0]', '$_[1]'),
+ '}',
+ ]);
+ }
+ catch {
+ $self->_throw_exception( CouldNotGenerateInlineAttributeMethod => instance => $self,
+ error => $_,
+ option => "writer"
+ );
+ };
+}
+
+sub _generate_predicate_method {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return sub {
+ $attr->has_value($_[0])
+ };
+}
+
+sub _generate_predicate_method_inline {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return try {
+ $self->_compile_code([
+ 'sub {',
+ $attr->_inline_has_value('$_[0]'),
+ '}',
+ ]);
+ }
+ catch {
+ $self->_throw_exception( CouldNotGenerateInlineAttributeMethod => instance => $self,
+ error => $_,
+ option => "predicate"
+ );
+ };
+}
+
+sub _generate_clearer_method {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return sub {
+ $attr->clear_value($_[0])
+ };
+}
+
+sub _generate_clearer_method_inline {
+ my $self = shift;
+ my $attr = $self->associated_attribute;
+
+ return try {
+ $self->_compile_code([
+ 'sub {',
+ $attr->_inline_clear_value('$_[0]'),
+ '}',
+ ]);
+ }
+ catch {
+ $self->_throw_exception( CouldNotGenerateInlineAttributeMethod => instance => $self,
+ error => $_,
+ option => "clearer"
+ );
+ };
+}
+
+1;
+
+# ABSTRACT: Method Meta Object for accessors
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method::Accessor - Method Meta Object for accessors
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 SYNOPSIS
+
+ use Class::MOP::Method::Accessor;
+
+ my $reader = Class::MOP::Method::Accessor->new(
+ attribute => $attribute,
+ is_inline => 1,
+ accessor_type => 'reader',
+ );
+
+ $reader->body->execute($instance); # call the reader method
+
+=head1 DESCRIPTION
+
+This is a subclass of C<Class::MOP::Method> which is used by
+C<Class::MOP::Attribute> to generate accessor code. It handles
+generation of readers, writers, predicates and clearers. For each type
+of method, it can either create a subroutine reference, or actually
+inline code by generating a string and C<eval>'ing it.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Method::Accessor->new(%options) >>
+
+This returns a new C<Class::MOP::Method::Accessor> based on the
+C<%options> provided.
+
+=over 4
+
+=item * attribute
+
+This is the C<Class::MOP::Attribute> for which accessors are being
+generated. This option is required.
+
+=item * accessor_type
+
+This is a string which should be one of "reader", "writer",
+"accessor", "predicate", or "clearer". This is the type of method
+being generated. This option is required.
+
+=item * is_inline
+
+This indicates whether or not the accessor should be inlined. This
+defaults to false.
+
+=item * name
+
+The method name (without a package name). This is required.
+
+=item * package_name
+
+The package name for the method. This is required.
+
+=back
+
+=item B<< $metamethod->accessor_type >>
+
+Returns the accessor type which was passed to C<new>.
+
+=item B<< $metamethod->is_inline >>
+
+Returns a boolean indicating whether or not the accessor is inlined.
+
+=item B<< $metamethod->associated_attribute >>
+
+This returns the L<Class::MOP::Attribute> object which was passed to
+C<new>.
+
+=item B<< $metamethod->body >>
+
+The method itself is I<generated> when the accessor object is
+constructed.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method/Constructor.pm b/lib/Class/MOP/Method/Constructor.pm
new file mode 100644
index 0000000..c8a30ac
--- /dev/null
+++ b/lib/Class/MOP/Method/Constructor.pm
@@ -0,0 +1,251 @@
+package Class::MOP::Method::Constructor;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed', 'weaken';
+use Try::Tiny;
+
+use parent 'Class::MOP::Method::Inlined';
+
+sub new {
+ my $class = shift;
+ my %options = @_;
+
+ (blessed $options{metaclass} && $options{metaclass}->isa('Class::MOP::Class'))
+ || $class->_throw_exception( MustSupplyAMetaclass => params => \%options,
+ class => $class
+ )
+ if $options{is_inline};
+
+ ($options{package_name} && $options{name})
+ || $class->_throw_exception( MustSupplyPackageNameAndName => params => \%options,
+ class => $class
+ );
+
+ my $self = $class->_new(\%options);
+
+ # we don't want this creating
+ # a cycle in the code, if not
+ # needed
+ weaken($self->{'associated_metaclass'});
+
+ $self->_initialize_body;
+
+ return $self;
+}
+
+sub _new {
+ my $class = shift;
+
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+
+ return bless {
+ # inherited from Class::MOP::Method
+ body => $params->{body},
+ # associated_metaclass => $params->{associated_metaclass}, # overridden
+ package_name => $params->{package_name},
+ name => $params->{name},
+ original_method => $params->{original_method},
+
+ # inherited from Class::MOP::Generated
+ is_inline => $params->{is_inline} || 0,
+ definition_context => $params->{definition_context},
+
+ # inherited from Class::MOP::Inlined
+ _expected_method_class => $params->{_expected_method_class},
+
+ # defined in this subclass
+ options => $params->{options} || {},
+ associated_metaclass => $params->{metaclass},
+ }, $class;
+}
+
+## accessors
+
+sub options { (shift)->{'options'} }
+sub associated_metaclass { (shift)->{'associated_metaclass'} }
+
+## method
+
+sub _initialize_body {
+ my $self = shift;
+ my $method_name = '_generate_constructor_method';
+
+ $method_name .= '_inline' if $self->is_inline;
+
+ $self->{'body'} = $self->$method_name;
+}
+
+sub _eval_environment {
+ my $self = shift;
+ return $self->associated_metaclass->_eval_environment;
+}
+
+sub _generate_constructor_method {
+ return sub { Class::MOP::Class->initialize(shift)->new_object(@_) }
+}
+
+sub _generate_constructor_method_inline {
+ my $self = shift;
+
+ my $meta = $self->associated_metaclass;
+
+ my @source = (
+ 'sub {',
+ $meta->_inline_new_object,
+ '}',
+ );
+
+ warn join("\n", @source) if $self->options->{debug};
+
+ my $code = try {
+ $self->_compile_code(\@source);
+ }
+ catch {
+ my $source = join("\n", @source);
+ $self->_throw_exception( CouldNotEvalConstructor => constructor_method => $self,
+ source => $source,
+ error => $_
+ );
+ };
+
+ return $code;
+}
+
+1;
+
+# ABSTRACT: Method Meta Object for constructors
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method::Constructor - Method Meta Object for constructors
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 SYNOPSIS
+
+ use Class::MOP::Method::Constructor;
+
+ my $constructor = Class::MOP::Method::Constructor->new(
+ metaclass => $metaclass,
+ options => {
+ debug => 1, # this is all for now
+ },
+ );
+
+ # calling the constructor ...
+ $constructor->body->execute($metaclass->name, %params);
+
+=head1 DESCRIPTION
+
+This is a subclass of L<Class::MOP::Method> which generates
+constructor methods.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Method::Constructor->new(%options) >>
+
+This creates a new constructor object. It accepts a hash reference of
+options.
+
+=over 8
+
+=item * metaclass
+
+This should be a L<Class::MOP::Class> object. It is required.
+
+=item * name
+
+The method name (without a package name). This is required.
+
+=item * package_name
+
+The package name for the method. This is required.
+
+=item * is_inline
+
+This indicates whether or not the constructor should be inlined. This
+defaults to false.
+
+=back
+
+=item B<< $metamethod->is_inline >>
+
+Returns a boolean indicating whether or not the constructor is
+inlined.
+
+=item B<< $metamethod->associated_metaclass >>
+
+This returns the L<Class::MOP::Class> object for the method.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method/Generated.pm b/lib/Class/MOP/Method/Generated.pm
new file mode 100644
index 0000000..740f5f5
--- /dev/null
+++ b/lib/Class/MOP/Method/Generated.pm
@@ -0,0 +1,142 @@
+package Class::MOP::Method::Generated;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Eval::Closure;
+
+use parent 'Class::MOP::Method';
+
+## accessors
+
+sub new {
+ $_[0]->_throw_exception( CannotCallAnAbstractBaseMethod => package_name => __PACKAGE__ );
+}
+
+sub _initialize_body {
+ $_[0]->_throw_exception( NoBodyToInitializeInAnAbstractBaseClass => package_name => __PACKAGE__ );
+}
+
+sub _generate_description {
+ my ( $self, $context ) = @_;
+ $context ||= $self->definition_context;
+
+ my $desc = "generated method";
+ my $origin = "unknown origin";
+
+ if (defined $context) {
+ if (defined $context->{description}) {
+ $desc = $context->{description};
+ }
+
+ if (defined $context->{file} || defined $context->{line}) {
+ $origin = "defined at "
+ . (defined $context->{file}
+ ? $context->{file} : "<unknown file>")
+ . " line "
+ . (defined $context->{line}
+ ? $context->{line} : "<unknown line>");
+ }
+ }
+
+ return "$desc ($origin)";
+}
+
+sub _compile_code {
+ my ( $self, @args ) = @_;
+ unshift @args, 'source' if @args % 2;
+ my %args = @args;
+
+ my $context = delete $args{context};
+ my $environment = $self->can('_eval_environment')
+ ? $self->_eval_environment
+ : {};
+
+ return eval_closure(
+ environment => $environment,
+ description => $self->_generate_description($context),
+ %args,
+ );
+}
+
+1;
+
+# ABSTRACT: Abstract base class for generated methods
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method::Generated - Abstract base class for generated methods
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This is a C<Class::MOP::Method> subclass which is subclassed by
+C<Class::MOP::Method::Accessor> and
+C<Class::MOP::Method::Constructor>.
+
+It is not intended to be used directly.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method/Inlined.pm b/lib/Class/MOP/Method/Inlined.pm
new file mode 100644
index 0000000..a075200
--- /dev/null
+++ b/lib/Class/MOP/Method/Inlined.pm
@@ -0,0 +1,195 @@
+package Class::MOP::Method::Inlined;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'refaddr';
+
+use parent 'Class::MOP::Method::Generated';
+
+sub _uninlined_body {
+ my $self = shift;
+
+ my $super_method
+ = $self->associated_metaclass->find_next_method_by_name( $self->name )
+ or return;
+
+ if ( $super_method->isa(__PACKAGE__) ) {
+ return $super_method->_uninlined_body;
+ }
+ else {
+ return $super_method->body;
+ }
+}
+
+sub can_be_inlined {
+ my $self = shift;
+ my $metaclass = $self->associated_metaclass;
+ my $class = $metaclass->name;
+
+ # If we don't find an inherited method, this is a rather weird
+ # case where we have no method in the inheritance chain even
+ # though we're expecting one to be there
+ my $inherited_method
+ = $metaclass->find_next_method_by_name( $self->name );
+
+ if ( $inherited_method
+ && $inherited_method->isa('Class::MOP::Method::Wrapped') ) {
+ warn "Not inlining '"
+ . $self->name
+ . "' for $class since it "
+ . "has method modifiers which would be lost if it were inlined\n";
+
+ return 0;
+ }
+
+ my $expected_class = $self->_expected_method_class
+ or return 1;
+
+ # if we are shadowing a method we first verify that it is
+ # compatible with the definition we are replacing it with
+ my $expected_method = $expected_class->can( $self->name );
+
+ if ( ! $expected_method ) {
+ warn "Not inlining '"
+ . $self->name
+ . "' for $class since ${expected_class}::"
+ . $self->name
+ . " is not defined\n";
+
+ return 0;
+ }
+
+ my $actual_method = $class->can( $self->name )
+ or return 1;
+
+ # the method is what we wanted (probably Moose::Object::new)
+ return 1
+ if refaddr($expected_method) == refaddr($actual_method);
+
+ # otherwise we have to check that the actual method is an inlined
+ # version of what we're expecting
+ if ( $inherited_method->isa(__PACKAGE__) ) {
+ if ( $inherited_method->_uninlined_body
+ && refaddr( $inherited_method->_uninlined_body )
+ == refaddr($expected_method) ) {
+ return 1;
+ }
+ }
+ elsif ( refaddr( $inherited_method->body )
+ == refaddr($expected_method) ) {
+ return 1;
+ }
+
+ my $warning
+ = "Not inlining '"
+ . $self->name
+ . "' for $class since it is not"
+ . " inheriting the default ${expected_class}::"
+ . $self->name . "\n";
+
+ if ( $self->isa("Class::MOP::Method::Constructor") ) {
+
+ # FIXME kludge, refactor warning generation to a method
+ $warning
+ .= "If you are certain you don't need to inline your"
+ . " constructor, specify inline_constructor => 0 in your"
+ . " call to $class->meta->make_immutable\n";
+ }
+
+ warn $warning;
+
+ return 0;
+}
+
+1;
+
+# ABSTRACT: Method base class for methods which have been inlined
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method::Inlined - Method base class for methods which have been inlined
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This is a L<Class::MOP::Method::Generated> subclass for methods which
+can be inlined.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< $metamethod->can_be_inlined >>
+
+This method returns true if the method in question can be inlined in
+the associated metaclass.
+
+If it cannot be inlined, it spits out a warning and returns false.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method/Meta.pm b/lib/Class/MOP/Method/Meta.pm
new file mode 100644
index 0000000..23b3567
--- /dev/null
+++ b/lib/Class/MOP/Method/Meta.pm
@@ -0,0 +1,169 @@
+package Class::MOP::Method::Meta;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Carp 'confess';
+use Scalar::Util 'blessed', 'weaken';
+
+use constant DEBUG_NO_META => $ENV{DEBUG_NO_META} ? 1 : 0;
+
+use parent 'Class::MOP::Method';
+
+sub _is_caller_mop_internal {
+ my $self = shift;
+ my ($caller) = @_;
+ return $caller =~ /^(?:Class::MOP|metaclass)(?:::|$)/;
+}
+
+sub _generate_meta_method {
+ my $method_self = shift;
+ my $metaclass = shift;
+ weaken($metaclass);
+
+ sub {
+ # this will be compiled out if the env var wasn't set
+ if (DEBUG_NO_META) {
+ confess "'meta' method called by MOP internals"
+ # it's okay to call meta methods on metaclasses, since we
+ # explicitly ask for them
+ if !$_[0]->isa('Class::MOP::Object')
+ && !$_[0]->isa('Class::MOP::Mixin')
+ # it's okay if the test itself calls ->meta, we only care about
+ # if the mop internals call ->meta
+ && $method_self->_is_caller_mop_internal(scalar caller);
+ }
+ # we must re-initialize so that it
+ # works as expected in subclasses,
+ # since metaclass instances are
+ # singletons, this is not really a
+ # big deal anyway.
+ $metaclass->initialize(blessed($_[0]) || $_[0])
+ };
+}
+
+sub wrap {
+ my ($class, @args) = @_;
+
+ unshift @args, 'body' if @args % 2 == 1;
+ my %params = @args;
+ $class->_throw_exception( CannotOverrideBodyOfMetaMethods => params => \%params,
+ class => $class
+ )
+ if $params{body};
+
+ my $metaclass_class = $params{associated_metaclass}->meta;
+ $params{body} = $class->_generate_meta_method($metaclass_class);
+ return $class->SUPER::wrap(%params);
+}
+
+sub _make_compatible_with {
+ my $self = shift;
+ my ($other) = @_;
+
+ # XXX: this is pretty gross. the issue here is that CMOP::Method::Meta
+ # objects are subclasses of CMOP::Method, but when we get to moose, they'll
+ # need to be compatible with Moose::Meta::Method, which isn't possible. the
+ # right solution here is to make ::Meta into a role that gets applied to
+ # whatever the method_metaclass happens to be and get rid of
+ # _meta_method_metaclass entirely, but that's not going to happen until
+ # we ditch cmop and get roles into the bootstrapping, so. i'm not
+ # maintaining the previous behavior of turning them into instances of the
+ # new method_metaclass because that's equally broken, and at least this way
+ # any issues will at least be detectable and potentially fixable. -doy
+ return $self unless $other->_is_compatible_with($self->_real_ref_name);
+
+ return $self->SUPER::_make_compatible_with(@_);
+}
+
+1;
+
+# ABSTRACT: Method Meta Object for C<meta> methods
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method::Meta - Method Meta Object for C<meta> methods
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This is a L<Class::MOP::Method> subclass which represents C<meta>
+methods installed into classes by Class::MOP.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Method::Wrapped->wrap($metamethod, %options) >>
+
+This is the constructor. It accepts a L<Class::MOP::Method> object and
+a hash of options. The options accepted are identical to the ones
+accepted by L<Class::MOP::Method>, except that C<body> cannot be passed
+(it will be generated automatically).
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Method/Wrapped.pm b/lib/Class/MOP/Method/Wrapped.pm
new file mode 100644
index 0000000..6b96c5f
--- /dev/null
+++ b/lib/Class/MOP/Method/Wrapped.pm
@@ -0,0 +1,331 @@
+package Class::MOP::Method::Wrapped;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed';
+
+use parent 'Class::MOP::Method';
+
+# NOTE:
+# this ugly beast is the result of trying
+# to micro optimize this as much as possible
+# while not completely loosing maintainability.
+# At this point it's "fast enough", after all
+# you can't get something for nothing :)
+my $_build_wrapped_method = sub {
+ my $modifier_table = shift;
+ my ($before, $after, $around) = (
+ $modifier_table->{before},
+ $modifier_table->{after},
+ $modifier_table->{around},
+ );
+ if (@$before && @$after) {
+ $modifier_table->{cache} = sub {
+ for my $c (@$before) { $c->(@_) };
+ my @rval;
+ ((defined wantarray) ?
+ ((wantarray) ?
+ (@rval = $around->{cache}->(@_))
+ :
+ ($rval[0] = $around->{cache}->(@_)))
+ :
+ $around->{cache}->(@_));
+ for my $c (@$after) { $c->(@_) };
+ return unless defined wantarray;
+ return wantarray ? @rval : $rval[0];
+ }
+ }
+ elsif (@$before && !@$after) {
+ $modifier_table->{cache} = sub {
+ for my $c (@$before) { $c->(@_) };
+ return $around->{cache}->(@_);
+ }
+ }
+ elsif (@$after && !@$before) {
+ $modifier_table->{cache} = sub {
+ my @rval;
+ ((defined wantarray) ?
+ ((wantarray) ?
+ (@rval = $around->{cache}->(@_))
+ :
+ ($rval[0] = $around->{cache}->(@_)))
+ :
+ $around->{cache}->(@_));
+ for my $c (@$after) { $c->(@_) };
+ return unless defined wantarray;
+ return wantarray ? @rval : $rval[0];
+ }
+ }
+ else {
+ $modifier_table->{cache} = $around->{cache};
+ }
+};
+
+sub wrap {
+ my ( $class, $code, %params ) = @_;
+
+ (blessed($code) && $code->isa('Class::MOP::Method'))
+ || $class->_throw_exception( CanOnlyWrapBlessedCode => params => \%params,
+ class => $class,
+ code => $code
+ );
+
+ my $modifier_table = {
+ cache => undef,
+ orig => $code->body,
+ before => [],
+ after => [],
+ around => {
+ cache => $code->body,
+ methods => [],
+ },
+ };
+ $_build_wrapped_method->($modifier_table);
+ return $class->SUPER::wrap(
+ sub { $modifier_table->{cache}->(@_) },
+ # get these from the original
+ # unless explicitly overridden
+ package_name => $params{package_name} || $code->package_name,
+ name => $params{name} || $code->name,
+ original_method => $code,
+
+ modifier_table => $modifier_table,
+ );
+}
+
+sub _new {
+ my $class = shift;
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+
+ return bless {
+ # inherited from Class::MOP::Method
+ 'body' => $params->{body},
+ 'associated_metaclass' => $params->{associated_metaclass},
+ 'package_name' => $params->{package_name},
+ 'name' => $params->{name},
+ 'original_method' => $params->{original_method},
+
+ # defined in this class
+ 'modifier_table' => $params->{modifier_table}
+ } => $class;
+}
+
+sub get_original_method {
+ my $code = shift;
+ $code->original_method;
+}
+
+sub add_before_modifier {
+ my $code = shift;
+ my $modifier = shift;
+ unshift @{$code->{'modifier_table'}->{before}} => $modifier;
+ $_build_wrapped_method->($code->{'modifier_table'});
+}
+
+sub before_modifiers {
+ my $code = shift;
+ return @{$code->{'modifier_table'}->{before}};
+}
+
+sub add_after_modifier {
+ my $code = shift;
+ my $modifier = shift;
+ push @{$code->{'modifier_table'}->{after}} => $modifier;
+ $_build_wrapped_method->($code->{'modifier_table'});
+}
+
+sub after_modifiers {
+ my $code = shift;
+ return @{$code->{'modifier_table'}->{after}};
+}
+
+{
+ # NOTE:
+ # this is another possible candidate for
+ # optimization as well. There is an overhead
+ # associated with the currying that, if
+ # eliminated might make around modifiers
+ # more manageable.
+ my $compile_around_method = sub {{
+ my $f1 = pop;
+ return $f1 unless @_;
+ my $f2 = pop;
+ push @_, sub { $f2->( $f1, @_ ) };
+ redo;
+ }};
+
+ sub add_around_modifier {
+ my $code = shift;
+ my $modifier = shift;
+ unshift @{$code->{'modifier_table'}->{around}->{methods}} => $modifier;
+ $code->{'modifier_table'}->{around}->{cache} = $compile_around_method->(
+ @{$code->{'modifier_table'}->{around}->{methods}},
+ $code->{'modifier_table'}->{orig}
+ );
+ $_build_wrapped_method->($code->{'modifier_table'});
+ }
+}
+
+sub around_modifiers {
+ my $code = shift;
+ return @{$code->{'modifier_table'}->{around}->{methods}};
+}
+
+sub _make_compatible_with {
+ my $self = shift;
+ my ($other) = @_;
+
+ # XXX: this is pretty gross. the issue here is that CMOP::Method::Wrapped
+ # objects are subclasses of CMOP::Method, but when we get to moose, they'll
+ # need to be compatible with Moose::Meta::Method, which isn't possible. the
+ # right solution here is to make ::Wrapped into a role that gets applied to
+ # whatever the method_metaclass happens to be and get rid of
+ # wrapped_method_metaclass entirely, but that's not going to happen until
+ # we ditch cmop and get roles into the bootstrapping, so. i'm not
+ # maintaining the previous behavior of turning them into instances of the
+ # new method_metaclass because that's equally broken, and at least this way
+ # any issues will at least be detectable and potentially fixable. -doy
+ return $self unless $other->_is_compatible_with($self->_real_ref_name);
+
+ return $self->SUPER::_make_compatible_with(@_);
+}
+
+1;
+
+# ABSTRACT: Method Meta Object for methods with before/after/around modifiers
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Method::Wrapped - Method Meta Object for methods with before/after/around modifiers
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This is a L<Class::MOP::Method> subclass which implements before,
+after, and around method modifiers.
+
+=head1 METHODS
+
+=head2 Construction
+
+=over 4
+
+=item B<< Class::MOP::Method::Wrapped->wrap($metamethod, %options) >>
+
+This is the constructor. It accepts a L<Class::MOP::Method> object and
+a hash of options.
+
+The options are:
+
+=over 8
+
+=item * name
+
+The method name (without a package name). This will be taken from the
+provided L<Class::MOP::Method> object if it is not provided.
+
+=item * package_name
+
+The package name for the method. This will be taken from the provided
+L<Class::MOP::Method> object if it is not provided.
+
+=item * associated_metaclass
+
+An optional L<Class::MOP::Class> object. This is the metaclass for the
+method's class.
+
+=back
+
+=item B<< $metamethod->get_original_method >>
+
+This returns the L<Class::MOP::Method> object that was passed to the
+constructor.
+
+=item B<< $metamethod->add_before_modifier($code) >>
+
+=item B<< $metamethod->add_after_modifier($code) >>
+
+=item B<< $metamethod->add_around_modifier($code) >>
+
+These methods all take a subroutine reference and apply it as a
+modifier to the original method.
+
+=item B<< $metamethod->before_modifiers >>
+
+=item B<< $metamethod->after_modifiers >>
+
+=item B<< $metamethod->around_modifiers >>
+
+These methods all return a list of subroutine references which are
+acting as the specified type of modifier.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/MiniTrait.pm b/lib/Class/MOP/MiniTrait.pm
new file mode 100644
index 0000000..4272901
--- /dev/null
+++ b/lib/Class/MOP/MiniTrait.pm
@@ -0,0 +1,113 @@
+package Class::MOP::MiniTrait;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Module::Runtime 'use_package_optimistically';
+
+sub apply {
+ my ( $to_class, $trait ) = @_;
+
+ for ( grep { !ref } $to_class, $trait ) {
+ use_package_optimistically($_);
+ $_ = Class::MOP::Class->initialize($_);
+ }
+
+ for my $meth ( grep { $_->package_name ne 'UNIVERSAL' } $trait->get_all_methods ) {
+ my $meth_name = $meth->name;
+ next if index($meth_name, '__') == 0; # skip private subs
+
+ if ( $to_class->find_method_by_name($meth_name) ) {
+ $to_class->add_around_method_modifier( $meth_name, $meth->body );
+ }
+ else {
+ $to_class->add_method( $meth_name, $meth->clone );
+ }
+ }
+}
+
+# We can't load this with use, since it may be loaded and used from Class::MOP
+# (via CMOP::Class, etc). However, if for some reason this module is loaded
+# _without_ first loading Class::MOP we need to require Class::MOP so we can
+# use it and CMOP::Class.
+require Class::MOP;
+
+1;
+
+# ABSTRACT: Extremely limited trait application
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::MiniTrait - Extremely limited trait application
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This package provides a single function, C<apply>, which does a half-assed job
+of applying a trait to a class. It exists solely for use inside Class::MOP and
+L<Moose> core classes.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Mixin.pm b/lib/Class/MOP/Mixin.pm
new file mode 100644
index 0000000..578448a
--- /dev/null
+++ b/lib/Class/MOP/Mixin.pm
@@ -0,0 +1,111 @@
+package Class::MOP::Mixin;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed';
+use Module::Runtime 'use_module';
+
+sub meta {
+ require Class::MOP::Class;
+ Class::MOP::Class->initialize( blessed( $_[0] ) || $_[0] );
+}
+
+sub _throw_exception {
+ my ($class, $exception_type, @args_to_exception) = @_;
+ die use_module( "Moose::Exception::$exception_type" )->new( @args_to_exception );
+}
+
+1;
+
+# ABSTRACT: Base class for mixin classes
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Mixin - Base class for mixin classes
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class provides a few methods which are useful in all metaclasses.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Mixin->meta >>
+
+This returns a L<Class::MOP::Class> object for the mixin class.
+
+=item B<< Class::MOP::Mixin->_throw_exception >>
+
+Throws an exception in the L<Moose::Exception> family. This should ONLY be
+used internally -- any callers outside Class::MOP::* should be using the
+version in L<Moose::Util> instead.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Mixin/AttributeCore.pm b/lib/Class/MOP/Mixin/AttributeCore.pm
new file mode 100644
index 0000000..9c96c6c
--- /dev/null
+++ b/lib/Class/MOP/Mixin/AttributeCore.pm
@@ -0,0 +1,125 @@
+package Class::MOP::Mixin::AttributeCore;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed';
+
+use parent 'Class::MOP::Mixin';
+
+sub has_accessor { defined $_[0]->{'accessor'} }
+sub has_reader { defined $_[0]->{'reader'} }
+sub has_writer { defined $_[0]->{'writer'} }
+sub has_predicate { defined $_[0]->{'predicate'} }
+sub has_clearer { defined $_[0]->{'clearer'} }
+sub has_builder { defined $_[0]->{'builder'} }
+sub has_init_arg { defined $_[0]->{'init_arg'} }
+sub has_default { exists $_[0]->{'default'} }
+sub has_initializer { defined $_[0]->{'initializer'} }
+sub has_insertion_order { defined $_[0]->{'insertion_order'} }
+
+sub _set_insertion_order { $_[0]->{'insertion_order'} = $_[1] }
+
+sub has_read_method { $_[0]->has_reader || $_[0]->has_accessor }
+sub has_write_method { $_[0]->has_writer || $_[0]->has_accessor }
+
+sub is_default_a_coderef {
+ # Uber hack because it is called from CMOP::Attribute constructor as
+ # $class->is_default_a_coderef(\%options)
+ my ($value) = ref $_[0] ? $_[0]->{'default'} : $_[1]->{'default'};
+
+ return unless ref($value);
+
+ return ref($value) eq 'CODE'
+ || ( blessed($value) && $value->isa('Class::MOP::Method') );
+}
+
+sub default {
+ my ( $self, $instance ) = @_;
+ if ( defined $instance && $self->is_default_a_coderef ) {
+ # if the default is a CODE ref, then we pass in the instance and
+ # default can return a value based on that instance. Somewhat crude,
+ # but works.
+ return $self->{'default'}->($instance);
+ }
+ $self->{'default'};
+}
+
+1;
+
+# ABSTRACT: Core attributes shared by attribute metaclasses
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Mixin::AttributeCore - Core attributes shared by attribute metaclasses
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class implements the core attributes (aka properties) shared by all
+attributes. See the L<Class::MOP::Attribute> documentation for API details.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Mixin/HasAttributes.pm b/lib/Class/MOP/Mixin/HasAttributes.pm
new file mode 100644
index 0000000..c76377d
--- /dev/null
+++ b/lib/Class/MOP/Mixin/HasAttributes.pm
@@ -0,0 +1,171 @@
+package Class::MOP::Mixin::HasAttributes;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed';
+
+use parent 'Class::MOP::Mixin';
+
+sub add_attribute {
+ my $self = shift;
+
+ my $attribute
+ = blessed( $_[0] ) ? $_[0] : $self->attribute_metaclass->new(@_);
+
+ ( $attribute->isa('Class::MOP::Mixin::AttributeCore') )
+ || $self->_throw_exception( AttributeMustBeAnClassMOPMixinAttributeCoreOrSubclass => attribute => $attribute,
+ class_name => $self->name,
+ );
+
+ $self->_attach_attribute($attribute);
+
+ my $attr_name = $attribute->name;
+
+ $self->remove_attribute($attr_name)
+ if $self->has_attribute($attr_name);
+
+ my $order = ( scalar keys %{ $self->_attribute_map } );
+ $attribute->_set_insertion_order($order);
+
+ $self->_attribute_map->{$attr_name} = $attribute;
+
+ # This method is called to allow for installing accessors. Ideally, we'd
+ # use method overriding, but then the subclass would be responsible for
+ # making the attribute, which would end up with lots of code
+ # duplication. Even more ideally, we'd use augment/inner, but this is
+ # Class::MOP!
+ $self->_post_add_attribute($attribute)
+ if $self->can('_post_add_attribute');
+
+ return $attribute;
+}
+
+sub has_attribute {
+ my ( $self, $attribute_name ) = @_;
+
+ ( defined $attribute_name )
+ || $self->_throw_exception( MustDefineAnAttributeName => class_name => $self->name );
+
+ exists $self->_attribute_map->{$attribute_name};
+}
+
+sub get_attribute {
+ my ( $self, $attribute_name ) = @_;
+
+ ( defined $attribute_name )
+ || $self->_throw_exception( MustDefineAnAttributeName => class_name => $self->name );
+
+ return $self->_attribute_map->{$attribute_name};
+}
+
+sub remove_attribute {
+ my ( $self, $attribute_name ) = @_;
+
+ ( defined $attribute_name )
+ || $self->_throw_exception( MustDefineAnAttributeName => class_name => $self->name );
+
+ my $removed_attribute = $self->_attribute_map->{$attribute_name};
+ return unless defined $removed_attribute;
+
+ delete $self->_attribute_map->{$attribute_name};
+
+ return $removed_attribute;
+}
+
+sub get_attribute_list {
+ my $self = shift;
+ keys %{ $self->_attribute_map };
+}
+
+sub _restore_metaattributes_from {
+ my $self = shift;
+ my ($old_meta) = @_;
+
+ for my $attr (sort { $a->insertion_order <=> $b->insertion_order }
+ map { $old_meta->get_attribute($_) }
+ $old_meta->get_attribute_list) {
+ $attr->_make_compatible_with($self->attribute_metaclass);
+ $self->add_attribute($attr);
+ }
+}
+
+1;
+
+# ABSTRACT: Methods for metaclasses which have attributes
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Mixin::HasAttributes - Methods for metaclasses which have attributes
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class implements methods for metaclasses which have attributes
+(L<Class::MOP::Class> and L<Moose::Meta::Role>). See L<Class::MOP::Class> for
+API details.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Mixin/HasMethods.pm b/lib/Class/MOP/Mixin/HasMethods.pm
new file mode 100644
index 0000000..1a27b69
--- /dev/null
+++ b/lib/Class/MOP/Mixin/HasMethods.pm
@@ -0,0 +1,304 @@
+package Class::MOP::Mixin::HasMethods;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Class::MOP::Method::Meta;
+
+use Scalar::Util 'blessed', 'reftype';
+use Sub::Name 'subname';
+
+use parent 'Class::MOP::Mixin';
+
+sub _meta_method_class { 'Class::MOP::Method::Meta' }
+
+sub _add_meta_method {
+ my $self = shift;
+ my ($name) = @_;
+ my $existing_method = $self->can('find_method_by_name')
+ ? $self->find_method_by_name($name)
+ : $self->get_method($name);
+ return if $existing_method
+ && $existing_method->isa($self->_meta_method_class);
+ $self->add_method(
+ $name => $self->_meta_method_class->wrap(
+ name => $name,
+ package_name => $self->name,
+ associated_metaclass => $self,
+ )
+ );
+}
+
+sub wrap_method_body {
+ my ( $self, %args ) = @_;
+
+ ( $args{body} && 'CODE' eq reftype $args{body} )
+ || $self->_throw_exception( CodeBlockMustBeACodeRef => instance => $self,
+ params => \%args
+ );
+ $self->method_metaclass->wrap(
+ package_name => $self->name,
+ %args,
+ );
+}
+
+sub add_method {
+ my ( $self, $method_name, $method ) = @_;
+ ( defined $method_name && length $method_name )
+ || $self->_throw_exception( MustDefineAMethodName => instance => $self );
+
+ my $package_name = $self->name;
+
+ my $body;
+ if ( blessed($method) && $method->isa('Class::MOP::Method') ) {
+ $body = $method->body;
+ if ( $method->package_name ne $package_name ) {
+ $method = $method->clone(
+ package_name => $package_name,
+ name => $method_name,
+ );
+ }
+
+ $method->attach_to_class($self);
+ }
+ else {
+ # If a raw code reference is supplied, its method object is not created.
+ # The method object won't be created until required.
+ $body = $method;
+ }
+
+ $self->_method_map->{$method_name} = $method;
+
+ my ($current_package, $current_name) = Class::MOP::get_code_info($body);
+
+ subname($package_name . '::' . $method_name, $body)
+ unless defined $current_name && $current_name !~ /^__ANON__/;
+
+ $self->add_package_symbol("&$method_name", $body);
+
+ # we added the method to the method map too, so it's still valid
+ $self->update_package_cache_flag;
+}
+
+sub _code_is_mine {
+ my ( $self, $code ) = @_;
+
+ my ( $code_package, $code_name ) = Class::MOP::get_code_info($code);
+
+ return ( $code_package && $code_package eq $self->name )
+ || ( $code_package eq 'constant' && $code_name eq '__ANON__' );
+}
+
+sub has_method {
+ my ( $self, $method_name ) = @_;
+
+ ( defined $method_name && length $method_name )
+ || $self->_throw_exception( MustDefineAMethodName => instance => $self );
+
+ my $method = $self->_get_maybe_raw_method($method_name)
+ or return;
+
+ return defined($self->_method_map->{$method_name} = $method);
+}
+
+sub get_method {
+ my ( $self, $method_name ) = @_;
+
+ ( defined $method_name && length $method_name )
+ || $self->_throw_exception( MustDefineAMethodName => instance => $self );
+
+ my $method = $self->_get_maybe_raw_method($method_name)
+ or return;
+
+ return $method if blessed($method) && $method->isa('Class::MOP::Method');
+
+ return $self->_method_map->{$method_name} = $self->wrap_method_body(
+ body => $method,
+ name => $method_name,
+ associated_metaclass => $self,
+ );
+}
+
+sub _get_maybe_raw_method {
+ my ( $self, $method_name ) = @_;
+
+ my $map_entry = $self->_method_map->{$method_name};
+ return $map_entry if defined $map_entry;
+
+ my $code = $self->get_package_symbol("&$method_name");
+
+ return unless $code && $self->_code_is_mine($code);
+
+ return $code;
+}
+
+sub remove_method {
+ my ( $self, $method_name ) = @_;
+
+ ( defined $method_name && length $method_name )
+ || $self->_throw_exception( MustDefineAMethodName => instance => $self );
+
+ my $removed_method = delete $self->_method_map->{$method_name};
+
+ $self->remove_package_symbol("&$method_name");
+
+ $removed_method->detach_from_class
+ if blessed($removed_method) && $removed_method->isa('Class::MOP::Method');
+
+ # still valid, since we just removed the method from the map
+ $self->update_package_cache_flag;
+
+ return $removed_method;
+}
+
+sub get_method_list {
+ my $self = shift;
+
+ return keys %{ $self->_full_method_map };
+}
+
+sub _get_local_methods {
+ my $self = shift;
+
+ return values %{ $self->_full_method_map };
+}
+
+sub _restore_metamethods_from {
+ my $self = shift;
+ my ($old_meta) = @_;
+
+ my $package_name = $self->name;
+
+ # Check if Perl debugger is enabled
+ my $debugger_enabled = ($^P & 0x10);
+ my $debug_method_info;
+
+ for my $method ($old_meta->_get_local_methods) {
+ my $method_name = $method->name;
+
+ # Track DB::sub information for this method if debugger is enabled.
+ # This contains original method filename and line numbers.
+ $debug_method_info = '';
+ if ($debugger_enabled) {
+ $debug_method_info = $DB::sub{$package_name . "::" . $method_name}
+ }
+
+ $method->_make_compatible_with($self->method_metaclass);
+ $self->add_method($method_name => $method);
+
+ # Restore method debug information, which can be clobbered by add_method.
+ # Note that we handle this here instead of in add_method, because we
+ # only want to preserve the original debug info in cases where we are
+ # restoring a method, not overwriting a method.
+ if ($debugger_enabled && $debug_method_info) {
+ $DB::sub{$package_name . "::" . $method_name} = $debug_method_info;
+ }
+ }
+}
+
+sub reset_package_cache_flag { (shift)->{'_package_cache_flag'} = undef }
+sub update_package_cache_flag {
+ my $self = shift;
+ # NOTE:
+ # we can manually update the cache number
+ # since we are actually adding the method
+ # to our cache as well. This avoids us
+ # having to regenerate the method_map.
+ # - SL
+ $self->{'_package_cache_flag'} = Class::MOP::check_package_cache_flag($self->name);
+}
+
+sub _full_method_map {
+ my $self = shift;
+
+ my $pkg_gen = Class::MOP::check_package_cache_flag($self->name);
+
+ if (($self->{_package_cache_flag_full} || -1) != $pkg_gen) {
+ # forcibly reify all method map entries
+ $self->get_method($_)
+ for $self->list_all_package_symbols('CODE');
+ $self->{_package_cache_flag_full} = $pkg_gen;
+ }
+
+ return $self->_method_map;
+}
+
+1;
+
+# ABSTRACT: Methods for metaclasses which have methods
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Mixin::HasMethods - Methods for metaclasses which have methods
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class implements methods for metaclasses which have methods
+(L<Class::MOP::Class> and L<Moose::Meta::Role>). See L<Class::MOP::Class> for
+API details.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Mixin/HasOverloads.pm b/lib/Class/MOP/Mixin/HasOverloads.pm
new file mode 100644
index 0000000..057551f
--- /dev/null
+++ b/lib/Class/MOP/Mixin/HasOverloads.pm
@@ -0,0 +1,237 @@
+package Class::MOP::Mixin::HasOverloads;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Class::MOP::Overload;
+
+use Devel::OverloadInfo 'overload_info';
+use Scalar::Util 'blessed';
+use Sub::Identify 'sub_name', 'stash_name';
+
+use overload ();
+
+use parent 'Class::MOP::Mixin';
+
+sub is_overloaded {
+ my $self = shift;
+ return overload::Overloaded($self->name);
+}
+
+sub get_overload_list {
+ my $self = shift;
+
+ my $info = $self->_overload_info;
+ return grep { $_ ne 'fallback' } keys %{$info}
+}
+
+sub get_all_overloaded_operators {
+ my $self = shift;
+ return map { $self->_overload_for($_) } $self->get_overload_list;
+}
+
+sub has_overloaded_operator {
+ my $self = shift;
+ my ($op) = @_;
+ return defined $self->_overload_info->{$op};
+}
+
+sub _overload_map {
+ $_[0]->{_overload_map} ||= {};
+}
+
+sub get_overloaded_operator {
+ my $self = shift;
+ my ($op) = @_;
+ return $self->_overload_map->{$op} ||= $self->_overload_for($op);
+}
+
+use constant _SET_FALLBACK_EACH_TIME => $] < 5.120;
+
+sub add_overloaded_operator {
+ my $self = shift;
+ my ( $op, $overload ) = @_;
+
+ my %p = ( associated_metaclass => $self );
+ if ( !ref $overload ) {
+ %p = (
+ %p,
+ operator => $op,
+ method_name => $overload,
+ associated_metaclass => $self,
+ );
+ $p{method} = $self->get_method($overload)
+ if $self->has_method($overload);
+ $overload = Class::MOP::Overload->new(%p);
+ }
+ elsif ( !blessed $overload) {
+ $overload = Class::MOP::Overload->new(
+ operator => $op,
+ coderef => $overload,
+ coderef_name => sub_name($overload),
+ coderef_package => stash_name($overload),
+ %p,
+ );
+ }
+
+ $overload->attach_to_class($self);
+ $self->_overload_map->{$op} = $overload;
+
+ my %overload = (
+ $op => $overload->has_coderef
+ ? $overload->coderef
+ : $overload->method_name
+ );
+
+ # Perl 5.10 and earlier appear to have a bug where setting a new
+ # overloading operator wipes out the fallback value unless we pass it each
+ # time.
+ if (_SET_FALLBACK_EACH_TIME) {
+ $overload{fallback} = $self->get_overload_fallback_value;
+ }
+
+ $self->name->overload::OVERLOAD(%overload);
+}
+
+sub remove_overloaded_operator {
+ my $self = shift;
+ my ($op) = @_;
+
+ delete $self->_overload_map->{$op};
+
+ # overload.pm provides no api for this - but the problem that makes this
+ # necessary has been fixed in 5.18
+ $self->get_or_add_package_symbol('%OVERLOAD')->{dummy}++
+ if $] < 5.017000;
+
+ $self->remove_package_symbol('&(' . $op);
+}
+
+sub get_overload_fallback_value {
+ my $self = shift;
+ return $self->_overload_info->{fallback}{value};
+}
+
+sub set_overload_fallback_value {
+ my $self = shift;
+ my $value = shift;
+
+ $self->name->overload::OVERLOAD( fallback => $value );
+}
+
+# We could cache this but we'd need some logic to clear it at all the right
+# times, which seems more tedious than it's worth.
+sub _overload_info {
+ my $self = shift;
+ return overload_info( $self->name ) || {};
+}
+
+sub _overload_for {
+ my $self = shift;
+ my $op = shift;
+
+ my $map = $self->_overload_map;
+ return $map->{$op} if $map->{$op};
+
+ my $info = $self->_overload_info->{$op};
+ return unless $info;
+
+ my %p = (
+ operator => $op,
+ associated_metaclass => $self,
+ );
+
+ if ( $info->{code} && !$info->{method_name} ) {
+ $p{coderef} = $info->{code};
+ @p{ 'coderef_package', 'coderef_name' }
+ = $info->{code_name} =~ /(.+)::([^:]+)/;
+ }
+ else {
+ $p{method_name} = $info->{method_name};
+ if ( $self->has_method( $p{method_name} ) ) {
+ $p{method} = $self->get_method( $p{method_name} );
+ }
+ }
+
+ return $map->{$op} = Class::MOP::Overload->new(%p);
+}
+
+1;
+
+# ABSTRACT: Methods for metaclasses which have overloads
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Mixin::HasOverloads - Methods for metaclasses which have overloads
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class implements methods for metaclasses which have overloads
+(L<Class::MOP::Clas> and L<Moose::Meta::Role>). See L<Class::MOP::Class> for
+API details.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Module.pm b/lib/Class/MOP/Module.pm
new file mode 100644
index 0000000..ddc83f7
--- /dev/null
+++ b/lib/Class/MOP/Module.pm
@@ -0,0 +1,213 @@
+package Class::MOP::Module;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use parent 'Class::MOP::Package';
+
+sub _new {
+ my $class = shift;
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+ return bless {
+ # Need to quote package to avoid a problem with PPI mis-parsing this
+ # as a package statement.
+
+ # from Class::MOP::Package
+ 'package' => $params->{package},
+ namespace => \undef,
+
+ # attributes
+ version => \undef,
+ authority => \undef
+ } => $class;
+}
+
+sub version {
+ my $self = shift;
+ ${$self->get_or_add_package_symbol('$VERSION')};
+}
+
+sub authority {
+ my $self = shift;
+ ${$self->get_or_add_package_symbol('$AUTHORITY')};
+}
+
+sub identifier {
+ my $self = shift;
+ join '-' => (
+ $self->name,
+ ($self->version || ()),
+ ($self->authority || ()),
+ );
+}
+
+sub create {
+ my $class = shift;
+ my @args = @_;
+
+ unshift @args, 'package' if @args % 2 == 1;
+ my %options = @args;
+
+ my $package = delete $options{package};
+ my $version = delete $options{version};
+ my $authority = delete $options{authority};
+
+ my $meta = $class->SUPER::create($package => %options);
+
+ $meta->_instantiate_module($version, $authority);
+
+ return $meta;
+}
+
+sub _anon_package_prefix { 'Class::MOP::Module::__ANON__::SERIAL::' }
+
+sub _anon_cache_key {
+ my $class = shift;
+ my %options = @_;
+ $class->_throw_exception( PackagesAndModulesAreNotCachable => class_name => $class,
+ params => \%options,
+ is_module => 1
+ );
+}
+
+sub _instantiate_module {
+ my($self, $version, $authority) = @_;
+ my $package_name = $self->name;
+
+ $self->add_package_symbol('$VERSION' => $version)
+ if defined $version;
+ $self->add_package_symbol('$AUTHORITY' => $authority)
+ if defined $authority;
+
+ return;
+}
+
+1;
+
+# ABSTRACT: Module Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Module - Module Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+A module is essentially a L<Class::MOP::Package> with metadata, in our
+case the version and authority.
+
+=head1 INHERITANCE
+
+B<Class::MOP::Module> is a subclass of L<Class::MOP::Package>.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Module->create($package, %options) >>
+
+Overrides C<create> from L<Class::MOP::Package> to provide these additional
+options:
+
+=over 4
+
+=item C<version>
+
+A version number, to be installed in the C<$VERSION> package global variable.
+
+=item C<authority>
+
+An authority, to be installed in the C<$AUTHORITY> package global variable.
+
+This is a legacy field and its use is not recommended.
+
+=back
+
+=item B<< $metamodule->version >>
+
+This is a read-only attribute which returns the C<$VERSION> of the
+package, if one exists.
+
+=item B<< $metamodule->authority >>
+
+This is a read-only attribute which returns the C<$AUTHORITY> of the
+package, if one exists.
+
+=item B<< $metamodule->identifier >>
+
+This constructs a string which combines the name, version and
+authority.
+
+=item B<< Class::MOP::Module->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Object.pm b/lib/Class/MOP/Object.pm
new file mode 100644
index 0000000..a5d0896
--- /dev/null
+++ b/lib/Class/MOP/Object.pm
@@ -0,0 +1,200 @@
+package Class::MOP::Object;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use parent 'Class::MOP::Mixin';
+use Scalar::Util 'blessed';
+use Module::Runtime;
+
+# introspection
+
+sub throw_error {
+ shift->_throw_exception( Legacy => message => join('', @_) );
+}
+
+sub _inline_throw_error {
+ my ( $self, $message ) = @_;
+ return 'die Module::Runtime::use_module("Moose::Exception::Legacy")->new(message => ' . $message. ')';
+}
+
+sub _new {
+ Class::MOP::class_of(shift)->new_object(@_);
+}
+
+# RANT:
+# Cmon, how many times have you written
+# the following code while debugging:
+#
+# use Data::Dumper;
+# warn Dumper $obj;
+#
+# It can get seriously annoying, so why
+# not just do this ...
+sub dump {
+ my $self = shift;
+ require Data::Dumper;
+ local $Data::Dumper::Maxdepth = shift || 1;
+ Data::Dumper::Dumper $self;
+}
+
+sub _real_ref_name {
+ my $self = shift;
+ return blessed($self);
+}
+
+sub _is_compatible_with {
+ my $self = shift;
+ my ($other_name) = @_;
+
+ return $self->isa($other_name);
+}
+
+sub _can_be_made_compatible_with {
+ my $self = shift;
+ return !$self->_is_compatible_with(@_)
+ && defined($self->_get_compatible_metaclass(@_));
+}
+
+sub _make_compatible_with {
+ my $self = shift;
+ my ($other_name) = @_;
+
+ my $new_metaclass = $self->_get_compatible_metaclass($other_name);
+
+ unless ( defined $new_metaclass ) {
+ $self->_throw_exception( CannotMakeMetaclassCompatible => superclass_name => $other_name,
+ class => $self,
+ );
+ }
+
+ # can't use rebless_instance here, because it might not be an actual
+ # subclass in the case of, e.g. moose role reconciliation
+ $new_metaclass->meta->_force_rebless_instance($self)
+ if blessed($self) ne $new_metaclass;
+
+ return $self;
+}
+
+sub _get_compatible_metaclass {
+ my $self = shift;
+ my ($other_name) = @_;
+
+ return $self->_get_compatible_metaclass_by_subclassing($other_name);
+}
+
+sub _get_compatible_metaclass_by_subclassing {
+ my $self = shift;
+ my ($other_name) = @_;
+ my $meta_name = blessed($self) ? $self->_real_ref_name : $self;
+
+ if ($meta_name->isa($other_name)) {
+ return $meta_name;
+ }
+ elsif ($other_name->isa($meta_name)) {
+ return $other_name;
+ }
+
+ return;
+}
+
+1;
+
+# ABSTRACT: Base class for metaclasses
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Object - Base class for metaclasses
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+This class is a very minimal base class for metaclasses.
+
+=head1 METHODS
+
+This class provides a few methods which are useful in all metaclasses.
+
+=over 4
+
+=item B<< Class::MOP::???->meta >>
+
+This returns a L<Class::MOP::Class> object.
+
+=item B<< $metaobject->dump($max_depth) >>
+
+This method uses L<Data::Dumper> to dump the object. You can pass an
+optional maximum depth, which will set C<$Data::Dumper::Maxdepth>. The
+default maximum depth is 1.
+
+=item B<< $metaclass->throw_error($message) >>
+
+This method calls L<Class::MOP::Mixin/_throw_exception> internally, with an object
+of class L<Moose::Exception::Legacy>.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Overload.pm b/lib/Class/MOP/Overload.pm
new file mode 100644
index 0000000..8ff81f5
--- /dev/null
+++ b/lib/Class/MOP/Overload.pm
@@ -0,0 +1,342 @@
+package Class::MOP::Overload;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use overload ();
+use Scalar::Util qw( blessed weaken );
+use Try::Tiny;
+
+use parent 'Class::MOP::Object';
+
+my %Operators = (
+ map { $_ => 1 }
+ grep { $_ ne 'fallback' }
+ map { split /\s+/ } values %overload::ops
+);
+
+sub new {
+ my ( $class, %params ) = @_;
+
+ unless ( defined $params{operator} ) {
+ $class->_throw_exception('OverloadRequiresAnOperator');
+ }
+ unless ( $Operators{ $params{operator} } ) {
+ $class->_throw_exception(
+ 'InvalidOverloadOperator',
+ operator => $params{operator},
+ );
+ }
+
+ unless ( defined $params{method_name} || $params{coderef} ) {
+ $class->_throw_exception(
+ 'OverloadRequiresAMethodNameOrCoderef',
+ operator => $params{operator},
+ );
+ }
+
+ if ( $params{coderef} ) {
+ unless ( defined $params{coderef_package}
+ && defined $params{coderef_name} ) {
+
+ $class->_throw_exception('OverloadRequiresNamesForCoderef');
+ }
+ }
+
+ if ( $params{method}
+ && !try { $params{method}->isa('Class::MOP::Method') } ) {
+
+ $class->_throw_exception('OverloadRequiresAMetaMethod');
+ }
+
+ if ( $params{associated_metaclass}
+ && !try { $params{associated_metaclass}->isa('Class::MOP::Module') } )
+ {
+
+ $class->_throw_exception('OverloadRequiresAMetaClass');
+ }
+
+ my @optional_attrs
+ = qw( method_name coderef coderef_package coderef_name method associated_metaclass );
+
+ return bless {
+ operator => $params{operator},
+ map { defined $params{$_} ? ( $_ => $params{$_} ) : () }
+ @optional_attrs
+ },
+ $class;
+}
+
+sub operator { $_[0]->{operator} }
+
+sub method_name { $_[0]->{method_name} }
+sub has_method_name { exists $_[0]->{method_name} }
+
+sub method { $_[0]->{method} }
+sub has_method { exists $_[0]->{method} }
+
+sub coderef { $_[0]->{coderef} }
+sub has_coderef { exists $_[0]->{coderef} }
+
+sub coderef_package { $_[0]->{coderef_package} }
+sub has_coderef_package { exists $_[0]->{coderef_package} }
+
+sub coderef_name { $_[0]->{coderef_name} }
+sub has_coderef_name { exists $_[0]->{coderef_name} }
+
+sub associated_metaclass { $_[0]->{associated_metaclass} }
+
+sub is_anonymous {
+ my $self = shift;
+ return $self->has_coderef && $self->coderef_name eq '__ANON__';
+}
+
+sub attach_to_class {
+ my ( $self, $class ) = @_;
+ $self->{associated_metaclass} = $class;
+ weaken $self->{associated_metaclass};
+}
+
+sub clone {
+ my $self = shift;
+
+ my $clone = bless { %{$self}, @_ }, blessed($self);
+ weaken $clone->{associated_metaclass} if $clone->{associated_metaclass};
+
+ $clone->_set_original_overload($self);
+
+ return $clone;
+}
+
+sub original_overload { $_[0]->{original_overload} }
+sub _set_original_overload { $_[0]->{original_overload} = $_[1] }
+
+sub _is_equal_to {
+ my $self = shift;
+ my $other = shift;
+
+ if ( $self->has_coderef ) {
+ return unless $other->has_coderef;
+ return $self->coderef == $other->coderef;
+ }
+ else {
+ return $self->method_name eq $other->method_name;
+ }
+}
+
+1;
+
+# ABSTRACT: Overload Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Overload - Overload Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 SYNOPSIS
+
+ my $meta = Class->meta;
+ my $overload = $meta->get_overloaded_operator('+');
+
+ if ( $overload->has_method_name ) {
+ print 'Method for + is ', $overload->method_name, "\n";
+ }
+ else {
+ print 'Overloading for + is implemented by ',
+ $overload->coderef_name, " sub\n";
+ }
+
+=head1 DESCRIPTION
+
+This class provides meta information for overloading in classes and roles.
+
+=head1 INHERITANCE
+
+C<Class::MOP::Overload> is a subclass of L<Class::MOP::Object>.
+
+=head1 METHODS
+
+This class provides the following methods:
+
+=head2 Class::MOP::Overload->new(%options)
+
+This method creates a new C<Class::MOP::Overload> object. It accepts a number
+of options:
+
+=over 4
+
+=item * operator
+
+This is a string that matches an operator known by the L<overload> module,
+such as C<""> or C<+>. This is required.
+
+=item * method_name
+
+The name of the method which implements the overloading. Note that this does
+not need to actually correspond to a real method, since it's okay to declare a
+not-yet-implemented overloading.
+
+Either this or the C<coderef> option must be passed.
+
+=item * method
+
+A L<Class::MOP::Method> object for the method which implements the
+overloading.
+
+This is optional.
+
+=item * coderef
+
+A coderef which implements the overloading.
+
+Either this or the C<method_name> option must be passed.
+
+=item * coderef_package
+
+The package where the coderef was defined.
+
+This is required if C<coderef> is passed.
+
+=item * coderef_name
+
+The name of the coderef. This can be "__ANON__".
+
+This is required if C<coderef> is passed.
+
+=item * associated_metaclass
+
+A L<Class::MOP::Module> object for the associated class or role.
+
+This is optional.
+
+=back
+
+=head2 $overload->operator
+
+Returns the operator for this overload object.
+
+=head2 $overload->method_name
+
+Returns the method name that implements overloading, if it has one.
+
+=head2 $overload->has_method_name
+
+Returns true if the object has a method name.
+
+=head2 $overload->method
+
+Returns the L<Class::MOP::Method> that implements overloading, if it has one.
+
+=head2 $overload->has_method
+
+Returns true if the object has a method.
+
+=head2 $overload->coderef
+
+Returns the coderef that implements overloading, if it has one.
+
+=head2 $overload->has_coderef
+
+Returns true if the object has a coderef.
+
+=head2 $overload->coderef_package
+
+Returns the package for the coderef that implements overloading, if it has
+one.
+
+=head2 $overload->has_coderef
+
+Returns true if the object has a coderef package.
+
+=head2 $overload->coderef_name
+
+Returns the sub name for the coderef that implements overloading, if it has
+one.
+
+=head2 $overload->has_coderef_name
+
+Returns true if the object has a coderef name.
+
+=head2 $overload->is_anonymous
+
+Returns true if the overloading is implemented by an anonymous coderef.
+
+=head2 $overload->associated_metaclass
+
+Returns the L<Class::MOP::Module> (class or role) that is associated with the
+overload object.
+
+=head2 $overload->clone
+
+Clones the overloading object, setting C<original_overload> in the process.
+
+=head2 $overload->original_overload
+
+For cloned objects, this returns the L<Class::MOP::Overload> object from which
+they were cloned. This can be used to determine the source of an overloading
+in a class that came from a role, for example.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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
diff --git a/lib/Class/MOP/Package.pm b/lib/Class/MOP/Package.pm
new file mode 100644
index 0000000..135ad68
--- /dev/null
+++ b/lib/Class/MOP/Package.pm
@@ -0,0 +1,464 @@
+package Class::MOP::Package;
+our $VERSION = '2.1405';
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed', 'weaken';
+use Devel::GlobalDestruction 'in_global_destruction';
+use Module::Runtime 'module_notional_filename';
+use Package::Stash;
+
+use parent 'Class::MOP::Object';
+
+# creation ...
+
+sub initialize {
+ my ( $class, @args ) = @_;
+
+ unshift @args, "package" if @args % 2;
+
+ my %options = @args;
+ my $package_name = delete $options{package};
+
+ # we hand-construct the class until we can bootstrap it
+ if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
+ return $meta;
+ } else {
+ my $meta = ( ref $class || $class )->_new({
+ 'package' => $package_name,
+ %options,
+ });
+ Class::MOP::store_metaclass_by_name($package_name, $meta);
+
+ Class::MOP::weaken_metaclass($package_name) if $options{weaken};
+
+
+ return $meta;
+ }
+}
+
+sub reinitialize {
+ my ( $class, @args ) = @_;
+
+ unshift @args, "package" if @args % 2;
+
+ my %options = @args;
+ my $package_name = delete $options{package};
+
+ (defined $package_name && $package_name
+ && (!blessed $package_name || $package_name->isa('Class::MOP::Package')))
+ || $class->_throw_exception( MustPassAPackageNameOrAnExistingClassMOPPackageInstance => params => \%options,
+ class => $class
+ );
+
+ $package_name = $package_name->name
+ if blessed $package_name;
+
+ Class::MOP::remove_metaclass_by_name($package_name);
+
+ $class->initialize($package_name, %options); # call with first arg form for compat
+}
+
+sub create {
+ my $class = shift;
+ my @args = @_;
+
+ my $meta = $class->initialize(@args);
+ my $filename = module_notional_filename($meta->name);
+ $INC{$filename} = '(set by Moose)'
+ unless exists $INC{$filename};
+
+ return $meta;
+}
+
+## ANON packages
+
+{
+ # NOTE:
+ # this should be sufficient, if you have a
+ # use case where it is not, write a test and
+ # I will change it.
+ my $ANON_SERIAL = 0;
+
+ my %ANON_PACKAGE_CACHE;
+
+ # NOTE:
+ # we need a sufficiently annoying prefix
+ # this should suffice for now, this is
+ # used in a couple of places below, so
+ # need to put it up here for now.
+ sub _anon_package_prefix { 'Class::MOP::Package::__ANON__::SERIAL::' }
+
+ sub is_anon {
+ my $self = shift;
+ no warnings 'uninitialized';
+ my $prefix = $self->_anon_package_prefix;
+ $self->name =~ /^\Q$prefix/;
+ }
+
+ sub create_anon {
+ my ($class, %options) = @_;
+
+ my $cache_ok = delete $options{cache};
+ $options{weaken} = !$cache_ok unless exists $options{weaken};
+
+ my $cache_key;
+ if ($cache_ok) {
+ $cache_key = $class->_anon_cache_key(%options);
+ undef $cache_ok if !defined($cache_key);
+ }
+
+ if ($cache_ok) {
+ if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
+ return $ANON_PACKAGE_CACHE{$cache_key};
+ }
+ }
+
+ my $package_name = $class->_anon_package_prefix . ++$ANON_SERIAL;
+
+ my $meta = $class->create($package_name, %options);
+
+ if ($cache_ok) {
+ $ANON_PACKAGE_CACHE{$cache_key} = $meta;
+ weaken($ANON_PACKAGE_CACHE{$cache_key});
+ }
+
+ return $meta;
+ }
+
+ sub _anon_cache_key {
+ my $class = shift;
+ my %options = @_;
+ $class->_throw_exception( PackagesAndModulesAreNotCachable => class_name => $class,
+ params => \%options,
+ is_module => 0
+ );
+ }
+
+ sub DESTROY {
+ my $self = shift;
+
+ return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
+
+ $self->_free_anon
+ if $self->is_anon;
+ }
+
+ sub _free_anon {
+ my $self = shift;
+ my $name = $self->name;
+
+ # Moose does a weird thing where it replaces the metaclass for
+ # class when fixing metaclass incompatibility. In that case,
+ # we don't want to clean out the namespace now. We can detect
+ # that because Moose will explicitly update the singleton
+ # cache in Class::MOP using store_metaclass_by_name, which
+ # means that the new metaclass will already exist in the cache
+ # by this point.
+ # The other options here are that $current_meta can be undef if
+ # remove_metaclass_by_name is called explicitly (since the hash
+ # entry is removed first, and then this destructor is called),
+ # or that $current_meta can be the same as $self, which happens
+ # when the metaclass goes out of scope (since the weak reference
+ # in the metaclass cache won't be freed until after this
+ # destructor runs).
+ my $current_meta = Class::MOP::get_metaclass_by_name($name);
+ return if defined($current_meta) && $current_meta ne $self;
+
+ my ($first_fragments, $last_fragment) = ($name =~ /^(.*)::(.*)$/);
+
+ no strict 'refs';
+ # clear @ISA first, to avoid a memory leak
+ # see https://rt.perl.org/rt3/Public/Bug/Display.html?id=92708
+ @{$name . '::ISA'} = ();
+ %{$name . '::'} = ();
+ delete ${$first_fragments . '::'}{$last_fragment . '::'};
+
+ Class::MOP::remove_metaclass_by_name($name);
+
+ delete $INC{module_notional_filename($name)};
+ }
+
+}
+
+sub _new {
+ my $class = shift;
+
+ return Class::MOP::Class->initialize($class)->new_object(@_)
+ if $class ne __PACKAGE__;
+
+ my $params = @_ == 1 ? $_[0] : {@_};
+
+ return bless {
+ # Need to quote package to avoid a problem with PPI mis-parsing this
+ # as a package statement.
+ 'package' => $params->{package},
+
+ # NOTE:
+ # because of issues with the Perl API
+ # to the typeglob in some versions, we
+ # need to just always grab a new
+ # reference to the hash in the accessor.
+ # Ideally we could just store a ref and
+ # it would Just Work, but oh well :\
+
+ namespace => \undef,
+
+ } => $class;
+}
+
+# Attributes
+
+# NOTE:
+# all these attribute readers will be bootstrapped
+# away in the Class::MOP bootstrap section
+
+sub _package_stash {
+ $_[0]->{_package_stash} ||= Package::Stash->new($_[0]->name)
+}
+sub namespace {
+ $_[0]->_package_stash->namespace
+}
+
+# Class attributes
+
+# ... these functions have to touch the symbol table itself,.. yuk
+
+sub add_package_symbol {
+ my $self = shift;
+ $self->_package_stash->add_symbol(@_);
+}
+
+sub remove_package_glob {
+ my $self = shift;
+ $self->_package_stash->remove_glob(@_);
+}
+
+# ... these functions deal with stuff on the namespace level
+
+sub has_package_symbol {
+ my $self = shift;
+ $self->_package_stash->has_symbol(@_);
+}
+
+sub get_package_symbol {
+ my $self = shift;
+ $self->_package_stash->get_symbol(@_);
+}
+
+sub get_or_add_package_symbol {
+ my $self = shift;
+ $self->_package_stash->get_or_add_symbol(@_);
+}
+
+sub remove_package_symbol {
+ my $self = shift;
+ $self->_package_stash->remove_symbol(@_);
+}
+
+sub list_all_package_symbols {
+ my $self = shift;
+ $self->_package_stash->list_all_symbols(@_);
+}
+
+sub get_all_package_symbols {
+ my $self = shift;
+ $self->_package_stash->get_all_symbols(@_);
+}
+
+1;
+
+# ABSTRACT: Package Meta Object
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::MOP::Package - Package Meta Object
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 DESCRIPTION
+
+The Package Protocol provides an abstraction of a Perl 5 package. A
+package is basically namespace, and this module provides methods for
+looking at and changing that namespace's symbol table.
+
+=head1 METHODS
+
+=over 4
+
+=item B<< Class::MOP::Package->initialize($package_name, %options) >>
+
+This method creates a new C<Class::MOP::Package> instance which
+represents specified package. If an existing metaclass object exists
+for the package, that will be returned instead. No options are valid at the
+package level.
+
+=item B<< Class::MOP::Package->reinitialize($package, %options) >>
+
+This method forcibly removes any existing metaclass for the package
+before calling C<initialize>. In contrast to C<initialize>, you may
+also pass an existing C<Class::MOP::Package> instance instead of just
+a package name as C<$package>.
+
+Do not call this unless you know what you are doing.
+
+=item B<< Class::MOP::Package->create($package, %options) >>
+
+Creates a new C<Class::MOP::Package> instance which represents the specified
+package, and also does some initialization of that package. Currently, this
+just does the same thing as C<initialize>, but is overridden in subclasses,
+such as C<Class::MOP::Class>.
+
+=item B<< Class::MOP::Package->create_anon(%options) >>
+
+Creates a new anonymous package. Valid keys for C<%options> are:
+
+=over 4
+
+=item C<cache>
+
+If this will be C<true> (the default is C<false>), the instance will be cached
+in C<Class::MOP>'s metaclass cache.
+
+=item C<weaken>
+
+If this is C<true> (the default C<true> when L<cache> is C<false>), the instance
+stored in C<Class::MOP>'s metaclass cache will be weakened, so that the
+anonymous package will be garbage collected when the returned instance goes out
+of scope.
+
+=back
+
+=item B<< $metapackage->is_anon >>
+
+Returns true if the package is an anonymous package.
+
+=item B<< $metapackage->name >>
+
+This is returns the package's name, as passed to the constructor.
+
+=item B<< $metapackage->namespace >>
+
+This returns a hash reference to the package's symbol table. The keys
+are symbol names and the values are typeglob references.
+
+=item B<< $metapackage->add_package_symbol($variable_name, $initial_value) >>
+
+This method accepts a variable name and an optional initial value. The
+C<$variable_name> must contain a leading sigil.
+
+This method creates the variable in the package's symbol table, and
+sets it to the initial value if one was provided.
+
+=item B<< $metapackage->get_package_symbol($variable_name) >>
+
+Given a variable name, this method returns the variable as a reference
+or undef if it does not exist. The C<$variable_name> must contain a
+leading sigil.
+
+=item B<< $metapackage->get_or_add_package_symbol($variable_name) >>
+
+Given a variable name, this method returns the variable as a reference.
+If it does not exist, a default value will be generated if possible. The
+C<$variable_name> must contain a leading sigil.
+
+=item B<< $metapackage->has_package_symbol($variable_name) >>
+
+Returns true if there is a package variable defined for
+C<$variable_name>. The C<$variable_name> must contain a leading sigil.
+
+=item B<< $metapackage->remove_package_symbol($variable_name) >>
+
+This will remove the package variable specified C<$variable_name>. The
+C<$variable_name> must contain a leading sigil.
+
+=item B<< $metapackage->remove_package_glob($glob_name) >>
+
+Given the name of a glob, this will remove that glob from the
+package's symbol table. Glob names do not include a sigil. Removing
+the glob removes all variables and subroutines with the specified
+name.
+
+=item B<< $metapackage->list_all_package_symbols($type_filter) >>
+
+This will list all the glob names associated with the current
+package. These names do not have leading sigils.
+
+You can provide an optional type filter, which should be one of
+'SCALAR', 'ARRAY', 'HASH', or 'CODE'.
+
+=item B<< $metapackage->get_all_package_symbols($type_filter) >>
+
+This works much like C<list_all_package_symbols>, but it returns a
+hash reference. The keys are glob names and the values are references
+to the value for that name.
+
+=item B<< Class::MOP::Package->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+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