X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FClass%2FMOP.pm;h=a646e00efd58866963c18f9dab1b9760a289c450;hb=8a7085c1c895cd5a263fcf27224ea0999d65e704;hp=1d0ea464b2e0199f06b2992fe0062bc9eef0a2f1;hpb=e8a38403cee329b9b4d2110294b2d098bb2c3cc9;p=gitmo%2FClass-MOP.git diff --git a/lib/Class/MOP.pm b/lib/Class/MOP.pm index 1d0ea46..a646e00 100644 --- a/lib/Class/MOP.pm +++ b/lib/Class/MOP.pm @@ -4,11 +4,34 @@ package Class::MOP; use strict; use warnings; +use 5.008; + use MRO::Compat; use Carp 'confess'; use Scalar::Util 'weaken'; +use Sub::Identify 'get_code_info'; + +BEGIN { + local $@; + eval { + require Sub::Name; + Sub::Name->import(qw(subname)); + 1 + } or eval 'sub subname { $_[1] }'; + + # this is either part of core or set up appropriately by MRO::Compat + *check_package_cache_flag = \&mro::get_pkg_gen; + + eval { + require Devel::GlobalDestruction; + Devel::GlobalDestruction->import("in_global_destruction"); + 1; + } or *in_global_destruction = sub () { !1 }; +} + + use Class::MOP::Class; use Class::MOP::Attribute; use Class::MOP::Method; @@ -16,10 +39,6 @@ use Class::MOP::Method; use Class::MOP::Immutable; BEGIN { - - our $VERSION = '0.65'; - our $AUTHORITY = 'cpan:STEVAN'; - *IS_RUNNING_ON_5_10 = ($] < 5.009_005) ? sub () { 0 } : sub () { 1 }; @@ -27,69 +46,26 @@ BEGIN { *HAVE_ISAREV = defined(&mro::get_isarev) ? sub () { 1 } : sub () { 1 }; +} - # NOTE: - # we may not use this yet, but once - # the get_code_info XS gets merged - # upstream to it, we will always use - # it. But for now it is just kinda - # extra overhead. - # - SL - require Sub::Identify; - - # stash these for a sec, and see how things go - my $_PP_subname = sub { $_[1] }; - my $_PP_get_code_info = \&Sub::Identify::get_code_info; +our $VERSION = '0.64_04'; +our $XS_VERSION = $VERSION; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; - if ($ENV{CLASS_MOP_NO_XS}) { - # NOTE: - # this is if you really want things - # to be slow, then you can force the - # no-XS rule this way, otherwise we - # make an effort to load as much of - # the XS as possible. - # - SL - no warnings 'prototype', 'redefine'; - - # this is either part of core or set up appropriately by MRO::Compat - *check_package_cache_flag = \&mro::get_pkg_gen; - - # our own version of Sub::Name - *subname = $_PP_subname; - # and the Sub::Identify version of the get_code_info - *get_code_info = $_PP_get_code_info; - } - else { - # now try our best to get as much - # of the XS loaded as possible - { - local $@; - eval { - require XSLoader; - XSLoader::load( 'Class::MOP', $VERSION ); - }; - die $@ if $@ && $@ !~ /object version|loadable object/; - - # okay, so the XS failed to load, so - # use the pure perl one instead. - *get_code_info = $_PP_get_code_info if $@; - } - - # get it from MRO::Compat - *check_package_cache_flag = \&mro::get_pkg_gen; - - # now try and load the Sub::Name - # module and use that as a means - # for naming our CVs, if not, we - # use the workaround instead. +# after that everything is loaded, if we're allowed try to load faster XS +# versions of various things +unless ($ENV{CLASS_MOP_NO_XS}) { + my $e = do { local $@; - if ( eval { require Sub::Name } ) { - *subname = \&Sub::Name::subname; - } - else { - *subname = $_PP_subname; - } - } + eval { + require XSLoader; + __PACKAGE__->XSLoader::load($XS_VERSION); + }; + $@; + }; + + die $e if $e && $e !~ /object version|loadable object/; } { @@ -236,15 +212,6 @@ Class::MOP::Package->meta->add_attribute( )) ); -# NOTE: -# use the metaclass to construct the meta-package -# which is a superclass of the metaclass itself :P -Class::MOP::Package->meta->add_method('initialize' => sub { - my $class = shift; - my $package_name = shift; - $class->meta->new_object('package' => $package_name, @_); -}); - ## -------------------------------------------------------- ## Class::MOP::Module @@ -479,40 +446,6 @@ Class::MOP::Attribute->meta->add_attribute( )) ); -# NOTE: (meta-circularity) -# This should be one of the last things done -# it will "tie the knot" with Class::MOP::Attribute -# so that it uses the attributes meta-objects -# to construct itself. -Class::MOP::Attribute->meta->add_method('new' => sub { - my ( $class, @args ) = @_; - - unshift @args, "name" if @args % 2 == 1; - my %options = @args; - - my $name = $options{name}; - - (defined $name && $name) - || confess "You must provide a name for the attribute"; - $options{init_arg} = $name - if not exists $options{init_arg}; - - if(exists $options{builder}){ - confess("builder must be a defined scalar value which is a method name") - if ref $options{builder} || !(defined $options{builder}); - confess("Setting both default and builder is not allowed.") - if exists $options{default}; - } else { - (Class::MOP::Attribute::is_default_a_coderef(\%options)) - || confess("References are not allowed as default values, you must ". - "wrap the default of '$name' in a CODE reference (ex: sub { [] } and not [])") - if exists $options{default} && ref $options{default}; - } - - # return the new object - $class->meta->new_object(%options); -}); - Class::MOP::Attribute->meta->add_method('clone' => sub { my $self = shift; $self->meta->clone_object($self, @_); @@ -544,25 +477,6 @@ Class::MOP::Method->meta->add_attribute( )) ); -# FIMXE prime candidate for immutablization -Class::MOP::Method->meta->add_method('wrap' => sub { - my ( $class, @args ) = @_; - - unshift @args, 'body' if @args % 2 == 1; - - my %options = @args; - my $code = $options{body}; - - ('CODE' eq ref($code)) - || confess "You must supply a CODE reference to bless, not (" . ($code || 'undef') . ")"; - - ($options{package_name} && $options{name}) - || confess "You must supply the package_name and name parameters"; - - # return the new object - $class->meta->new_object(%options); -}); - Class::MOP::Method->meta->add_method('clone' => sub { my $self = shift; $self->meta->clone_object($self, @_); @@ -590,15 +504,6 @@ Class::MOP::Method::Generated->meta->add_attribute( )) ); -Class::MOP::Method::Generated->meta->add_method('new' => sub { - my ($class, %options) = @_; - ($options{package_name} && $options{name}) - || confess "You must supply the package_name and name parameters"; - my $self = $class->meta->new_object(%options); - $self->initialize_body; - $self; -}); - ## -------------------------------------------------------- ## Class::MOP::Method::Accessor @@ -616,36 +521,6 @@ Class::MOP::Method::Accessor->meta->add_attribute( )) ); -Class::MOP::Method::Accessor->meta->add_method('new' => sub { - my $class = shift; - my %options = @_; - - (exists $options{attribute}) - || confess "You must supply an attribute to construct with"; - - (exists $options{accessor_type}) - || confess "You must supply an accessor_type to construct with"; - - (Scalar::Util::blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute')) - || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance"; - - ($options{package_name} && $options{name}) - || confess "You must supply the package_name and name parameters"; - - # return the new object - my $self = $class->meta->new_object(%options); - - # we don't want this creating - # a cycle in the code, if not - # needed - Scalar::Util::weaken($self->{'attribute'}); - - $self->initialize_body; - - $self; -}); - - ## -------------------------------------------------------- ## Class::MOP::Method::Constructor @@ -667,30 +542,6 @@ Class::MOP::Method::Constructor->meta->add_attribute( )) ); -Class::MOP::Method::Constructor->meta->add_method('new' => sub { - my $class = shift; - my %options = @_; - - (Scalar::Util::blessed $options{metaclass} && $options{metaclass}->isa('Class::MOP::Class')) - || confess "You must pass a metaclass instance if you want to inline" - if $options{is_inline}; - - ($options{package_name} && $options{name}) - || confess "You must supply the package_name and name parameters"; - - # return the new object - my $self = $class->meta->new_object(%options); - - # we don't want this creating - # a cycle in the code, if not - # needed - Scalar::Util::weaken($self->{'associated_metaclass'}); - - $self->initialize_body; - - $self; -}); - ## -------------------------------------------------------- ## Class::MOP::Instance @@ -699,19 +550,36 @@ Class::MOP::Method::Constructor->meta->add_method('new' => sub { # included for completeness Class::MOP::Instance->meta->add_attribute( - Class::MOP::Attribute->new('associated_metaclass') + Class::MOP::Attribute->new('associated_metaclass', + reader => { associated_metaclass => \&Class::MOP::Instance::associated_metaclass }, + ), ); Class::MOP::Instance->meta->add_attribute( - Class::MOP::Attribute->new('attributes') + 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 }, + ), ); Class::MOP::Instance->meta->add_attribute( - Class::MOP::Attribute->new('slots') + Class::MOP::Attribute->new('attributes', + reader => { attributes => \&Class::MOP::Instance::get_all_attributes }, + ), ); Class::MOP::Instance->meta->add_attribute( - Class::MOP::Attribute->new('slot_hash') + Class::MOP::Attribute->new('slots', + reader => { slots => \&Class::MOP::Instance::slots }, + ), +); + +Class::MOP::Instance->meta->add_attribute( + Class::MOP::Attribute->new('slot_hash', + reader => { slot_hash => \&Class::MOP::Instance::slot_hash }, + ), ); @@ -719,17 +587,6 @@ Class::MOP::Instance->meta->add_attribute( # for the constructor to be able to use it Class::MOP::Instance->meta->get_meta_instance; -Class::MOP::Instance->meta->add_method('new' => sub { - my $class = shift; - my $options = $class->BUILDARGS(@_); - - my $self = $class->meta->new_object(%$options); - - Scalar::Util::weaken($self->{'associated_metaclass'}); - - $self; -}); - # pretend the add_method never happenned. it hasn't yet affected anything undef Class::MOP::Instance->meta->{_package_cache_flag}; @@ -744,8 +601,10 @@ undef Class::MOP::Instance->meta->{_package_cache_flag}; # no actual benefits. $_->meta->make_immutable( - inline_constructor => 0, - inline_accessors => 0, + inline_constructor => 1, + replace_constructor => 1, + constructor_name => "_new", + inline_accessors => 0, ) for qw/ Class::MOP::Package Class::MOP::Module @@ -1009,6 +868,13 @@ If possible, we will load the L module and this will function as C does, otherwise it will just return the C<$code> argument. +=item B + +If L is available, this returns true under global +destruction. + +Otherwise it's a constant returning false. + =back =head2 Metaclass cache functions