use Class::MOP::Immutable;
BEGIN {
- our $VERSION = '0.59';
+
+ our $VERSION = '0.65';
our $AUTHORITY = 'cpan:STEVAN';
*IS_RUNNING_ON_5_10 = ($] < 5.009_005)
? sub () { 0 }
: sub () { 1 };
+ *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
# - SL
no warnings 'prototype', 'redefine';
- unless (IS_RUNNING_ON_5_10()) {
- # get this from MRO::Compat ...
- *check_package_cache_flag = \&MRO::Compat::__get_pkg_gen_pp;
- }
- else {
- # NOTE:
- # but if we are running 5.10
- # there is no need to use the
- # Pure Perl version since we
- # can use the built in mro
- # version instead.
- # - SL
- *check_package_cache_flag = \&mro::get_pkg_gen;
- }
+ # 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
sub load_class {
my $class = shift;
- # see if this is already
- # loaded in the symbol table
- return 1 if is_class_loaded($class);
- # otherwise require it ...
- my $file = $class . '.pm';
- $file =~ s{::}{/}g;
- eval { CORE::require($file) };
- confess "Could not load class ($class) because : $@" if $@;
+
+ if (ref($class) || !defined($class) || !length($class)) {
+ my $display = defined($class) ? $class : 'undef';
+ confess "Invalid class name ($display)";
+ }
+
+ # if the class is not already loaded in the symbol table..
+ unless (is_class_loaded($class)) {
+ # require it
+ my $file = $class . '.pm';
+ $file =~ s{::}{/}g;
+ eval { CORE::require($file) };
+ confess "Could not load class ($class) because : $@" if $@;
+ }
+
+ # initialize a metaclass if necessary
unless (does_metaclass_exist($class)) {
eval { Class::MOP::Class->initialize($class) };
confess "Could not initialize class ($class) because : $@" if $@;
}
- 1; # return true if it worked
+
+ return get_metaclass_by_name($class);
}
sub is_class_loaded {
my $class = shift;
- no strict 'refs';
- return 1 if defined ${"${class}::VERSION"} || defined @{"${class}::ISA"};
- foreach my $symbol (keys %{"${class}::"}) {
- next if substr($symbol, -2, 2) eq '::';
- return 1 if defined &{"${class}::${symbol}"};
+
+ return 0 if ref($class) || !defined($class) || !length($class);
+
+ # walk the symbol table tree to avoid autovififying
+ # \*{${main::}{"Foo::"}} == \*main::Foo::
+
+ my $pack = \*::;
+ foreach my $part (split('::', $class)) {
+ return 0 unless exists ${$$pack}{"${part}::"};
+ $pack = \*{${$$pack}{"${part}::"}};
+ }
+
+ # check for $VERSION or @ISA
+ return 1 if exists ${$$pack}{VERSION}
+ && defined *{${$$pack}{VERSION}}{SCALAR};
+ return 1 if exists ${$$pack}{ISA}
+ && defined *{${$$pack}{ISA}}{ARRAY};
+
+ # check for any method
+ foreach ( keys %{$$pack} ) {
+ next if substr($_, -2, 2) eq '::';
+
+ my $glob = ${$$pack}{$_} || next;
+
+ # constant subs
+ if ( IS_RUNNING_ON_5_10 ) {
+ return 1 if ref $glob eq 'SCALAR';
+ }
+
+ return 1 if defined *{$glob}{CODE};
}
+
+ # fail
return 0;
}
## Class::MOP::Package
Class::MOP::Package->meta->add_attribute(
- Class::MOP::Attribute->new('$!package' => (
+ Class::MOP::Attribute->new('package' => (
reader => {
# NOTE: we need to do this in order
# for the instance meta-object to
);
Class::MOP::Package->meta->add_attribute(
- Class::MOP::Attribute->new('%!namespace' => (
+ Class::MOP::Attribute->new('namespace' => (
reader => {
# NOTE:
# we just alias the original method
# the metaclass, isn't abstraction great :)
Class::MOP::Module->meta->add_attribute(
- Class::MOP::Attribute->new('$!version' => (
+ Class::MOP::Attribute->new('version' => (
reader => {
# NOTE:
# we just alias the original method
# well.
Class::MOP::Module->meta->add_attribute(
- Class::MOP::Attribute->new('$!authority' => (
+ Class::MOP::Attribute->new('authority' => (
reader => {
# NOTE:
# we just alias the original method
## Class::MOP::Class
Class::MOP::Class->meta->add_attribute(
- Class::MOP::Attribute->new('%!attributes' => (
+ Class::MOP::Attribute->new('attributes' => (
reader => {
# NOTE: we need to do this in order
# for the instance meta-object to
);
Class::MOP::Class->meta->add_attribute(
- Class::MOP::Attribute->new('%!methods' => (
+ Class::MOP::Attribute->new('methods' => (
init_arg => 'methods',
reader => {
# NOTE:
);
Class::MOP::Class->meta->add_attribute(
- Class::MOP::Attribute->new('@!superclasses' => (
+ Class::MOP::Attribute->new('superclasses' => (
accessor => {
# NOTE:
# we just alias the original method
);
Class::MOP::Class->meta->add_attribute(
- Class::MOP::Attribute->new('$!attribute_metaclass' => (
+ Class::MOP::Attribute->new('attribute_metaclass' => (
reader => {
# NOTE:
# we just alias the original method
);
Class::MOP::Class->meta->add_attribute(
- Class::MOP::Attribute->new('$!method_metaclass' => (
+ Class::MOP::Attribute->new('method_metaclass' => (
reader => {
# NOTE:
# we just alias the original method
);
Class::MOP::Class->meta->add_attribute(
- Class::MOP::Attribute->new('$!instance_metaclass' => (
+ Class::MOP::Attribute->new('instance_metaclass' => (
reader => {
# NOTE: we need to do this in order
# for the instance meta-object to
## Class::MOP::Attribute
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!name' => (
+ Class::MOP::Attribute->new('name' => (
init_arg => 'name',
reader => {
# NOTE: we need to do this in order
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!associated_class' => (
+ Class::MOP::Attribute->new('associated_class' => (
init_arg => 'associated_class',
reader => {
# NOTE: we need to do this in order
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!accessor' => (
+ Class::MOP::Attribute->new('accessor' => (
init_arg => 'accessor',
reader => { 'accessor' => \&Class::MOP::Attribute::accessor },
predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!reader' => (
+ Class::MOP::Attribute->new('reader' => (
init_arg => 'reader',
reader => { 'reader' => \&Class::MOP::Attribute::reader },
predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!initializer' => (
+ Class::MOP::Attribute->new('initializer' => (
init_arg => 'initializer',
reader => { 'initializer' => \&Class::MOP::Attribute::initializer },
predicate => { 'has_initializer' => \&Class::MOP::Attribute::has_initializer },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!writer' => (
+ Class::MOP::Attribute->new('writer' => (
init_arg => 'writer',
reader => { 'writer' => \&Class::MOP::Attribute::writer },
predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!predicate' => (
+ Class::MOP::Attribute->new('predicate' => (
init_arg => 'predicate',
reader => { 'predicate' => \&Class::MOP::Attribute::predicate },
predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!clearer' => (
+ Class::MOP::Attribute->new('clearer' => (
init_arg => 'clearer',
reader => { 'clearer' => \&Class::MOP::Attribute::clearer },
predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!builder' => (
+ Class::MOP::Attribute->new('builder' => (
init_arg => 'builder',
reader => { 'builder' => \&Class::MOP::Attribute::builder },
predicate => { 'has_builder' => \&Class::MOP::Attribute::has_builder },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!init_arg' => (
+ Class::MOP::Attribute->new('init_arg' => (
init_arg => 'init_arg',
reader => { 'init_arg' => \&Class::MOP::Attribute::init_arg },
predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('$!default' => (
+ Class::MOP::Attribute->new('default' => (
init_arg => 'default',
# default has a custom 'reader' method ...
predicate => { 'has_default' => \&Class::MOP::Attribute::has_default },
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('@!associated_methods' => (
+ Class::MOP::Attribute->new('associated_methods' => (
init_arg => 'associated_methods',
reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
default => sub { [] }
# so that it uses the attributes meta-objects
# to construct itself.
Class::MOP::Attribute->meta->add_method('new' => sub {
- my $class = shift;
- my $name = shift;
- my %options = @_;
+ 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";
"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(name => $name, %options);
+ $class->meta->new_object(%options);
});
Class::MOP::Attribute->meta->add_method('clone' => sub {
## --------------------------------------------------------
## Class::MOP::Method
-
Class::MOP::Method->meta->add_attribute(
- Class::MOP::Attribute->new('&!body' => (
+ Class::MOP::Attribute->new('body' => (
init_arg => 'body',
reader => { 'body' => \&Class::MOP::Method::body },
))
);
Class::MOP::Method->meta->add_attribute(
- Class::MOP::Attribute->new('$!package_name' => (
+ Class::MOP::Attribute->new('associated_metaclass' => (
+ init_arg => 'associated_metaclass',
+ reader => { 'associated_metaclass' => \&Class::MOP::Method::associated_metaclass },
+ ))
+);
+
+Class::MOP::Method->meta->add_attribute(
+ Class::MOP::Attribute->new('package_name' => (
init_arg => 'package_name',
reader => { 'package_name' => \&Class::MOP::Method::package_name },
))
);
Class::MOP::Method->meta->add_attribute(
- Class::MOP::Attribute->new('$!name' => (
+ Class::MOP::Attribute->new('name' => (
init_arg => 'name',
reader => { 'name' => \&Class::MOP::Method::name },
))
);
Class::MOP::Method->meta->add_method('wrap' => sub {
- my $class = shift;
- my $code = shift;
- my %options = @_;
+ 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') . ")";
|| confess "You must supply the package_name and name parameters";
# return the new object
- $class->meta->new_object(body => $code, %options);
+ $class->meta->new_object(%options);
});
Class::MOP::Method->meta->add_method('clone' => sub {
# practices of attributes, but we put
# it here for completeness
Class::MOP::Method::Wrapped->meta->add_attribute(
- Class::MOP::Attribute->new('%!modifier_table')
+ Class::MOP::Attribute->new('modifier_table')
);
## --------------------------------------------------------
## Class::MOP::Method::Generated
Class::MOP::Method::Generated->meta->add_attribute(
- Class::MOP::Attribute->new('$!is_inline' => (
+ Class::MOP::Attribute->new('is_inline' => (
init_arg => 'is_inline',
reader => { 'is_inline' => \&Class::MOP::Method::Generated::is_inline },
default => 0,
## Class::MOP::Method::Accessor
Class::MOP::Method::Accessor->meta->add_attribute(
- Class::MOP::Attribute->new('$!attribute' => (
+ Class::MOP::Attribute->new('attribute' => (
init_arg => 'attribute',
reader => {
'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute
);
Class::MOP::Method::Accessor->meta->add_attribute(
- Class::MOP::Attribute->new('$!accessor_type' => (
+ Class::MOP::Attribute->new('accessor_type' => (
init_arg => 'accessor_type',
reader => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
))
# we don't want this creating
# a cycle in the code, if not
# needed
- Scalar::Util::weaken($self->{'$!attribute'});
+ Scalar::Util::weaken($self->{'attribute'});
$self->initialize_body;
## Class::MOP::Method::Constructor
Class::MOP::Method::Constructor->meta->add_attribute(
- Class::MOP::Attribute->new('%!options' => (
+ Class::MOP::Attribute->new('options' => (
init_arg => 'options',
reader => {
'options' => \&Class::MOP::Method::Constructor::options
);
Class::MOP::Method::Constructor->meta->add_attribute(
- Class::MOP::Attribute->new('$!associated_metaclass' => (
+ Class::MOP::Attribute->new('associated_metaclass' => (
init_arg => 'metaclass',
reader => {
'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass
# we don't want this creating
# a cycle in the code, if not
# needed
- Scalar::Util::weaken($self->{'$!associated_metaclass'});
+ Scalar::Util::weaken($self->{'associated_metaclass'});
$self->initialize_body;
# included for completeness
Class::MOP::Instance->meta->add_attribute(
- Class::MOP::Attribute->new('$!meta')
+ Class::MOP::Attribute->new('associated_metaclass')
+);
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('attributes')
+);
+
+Class::MOP::Instance->meta->add_attribute(
+ Class::MOP::Attribute->new('slots')
);
Class::MOP::Instance->meta->add_attribute(
- Class::MOP::Attribute->new('@!slots')
+ Class::MOP::Attribute->new('slot_hash')
);
+
+# 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;
+
+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};
+
## --------------------------------------------------------
## Now close all the Class::MOP::* classes
allows us to take advantage of new 5.10 features and stay backwards
compat.
+=item I<HAVE_ISAREV>
+
+Whether or not C<mro> provides C<get_isarev>, a much faster way to get all the
+subclasses of a certain class.
+
=back
=head2 Utility functions