microoptimize Class::MOP::Class::initialize since it's called so often
[gitmo/Class-MOP.git] / lib / Class / MOP.pm
CommitLineData
94b19069 1
2package Class::MOP;
3
4use strict;
5use warnings;
6
3cf322a0 7use MRO::Compat;
8
4c105333 9use Carp 'confess';
10use Scalar::Util 'weaken';
8b978dd5 11
2eb717d5 12use Class::MOP::Class;
13use Class::MOP::Attribute;
14use Class::MOP::Method;
15
c23184fc 16use Class::MOP::Immutable;
857f87a7 17
b1f5f41d 18BEGIN {
70ad0655 19
2e5c1a3f 20 our $VERSION = '0.65';
b1f5f41d 21 our $AUTHORITY = 'cpan:STEVAN';
22
11b56828 23 *IS_RUNNING_ON_5_10 = ($] < 5.009_005)
24 ? sub () { 0 }
4c105333 25 : sub () { 1 };
46b23b44 26
9efe16ca 27 *HAVE_ISAREV = defined(&mro::get_isarev)
28 ? sub () { 1 }
29 : sub () { 1 };
30
4c105333 31 # NOTE:
32 # we may not use this yet, but once
33 # the get_code_info XS gets merged
34 # upstream to it, we will always use
35 # it. But for now it is just kinda
36 # extra overhead.
37 # - SL
38 require Sub::Identify;
39
40 # stash these for a sec, and see how things go
41 my $_PP_subname = sub { $_[1] };
a982eca7 42 my $_PP_get_code_info = \&Sub::Identify::get_code_info;
4c105333 43
e2d4fc55 44 if ($ENV{CLASS_MOP_NO_XS}) {
4c105333 45 # NOTE:
46 # this is if you really want things
47 # to be slow, then you can force the
48 # no-XS rule this way, otherwise we
49 # make an effort to load as much of
50 # the XS as possible.
51 # - SL
52 no warnings 'prototype', 'redefine';
6c34db07 53
3c489bcb 54 # this is either part of core or set up appropriately by MRO::Compat
55 *check_package_cache_flag = \&mro::get_pkg_gen;
56
4c105333 57 # our own version of Sub::Name
58 *subname = $_PP_subname;
59 # and the Sub::Identify version of the get_code_info
60 *get_code_info = $_PP_get_code_info;
61 }
62 else {
63 # now try our best to get as much
64 # of the XS loaded as possible
65 {
66 local $@;
67 eval {
68 require XSLoader;
69 XSLoader::load( 'Class::MOP', $VERSION );
70 };
71 die $@ if $@ && $@ !~ /object version|loadable object/;
72
73 # okay, so the XS failed to load, so
74 # use the pure perl one instead.
75 *get_code_info = $_PP_get_code_info if $@;
76 }
77
78 # get it from MRO::Compat
79 *check_package_cache_flag = \&mro::get_pkg_gen;
80
81 # now try and load the Sub::Name
82 # module and use that as a means
83 # for naming our CVs, if not, we
84 # use the workaround instead.
85 if ( eval { require Sub::Name } ) {
6c34db07 86 *subname = \&Sub::Name::subname;
4c105333 87 }
88 else {
89 *subname = $_PP_subname;
90 }
91 }
b1f5f41d 92}
e0e4674a 93
be7677c7 94{
95 # Metaclasses are singletons, so we cache them here.
96 # there is no need to worry about destruction though
97 # because they should die only when the program dies.
98 # After all, do package definitions even get reaped?
1d68af04 99 my %METAS;
100
101 # means of accessing all the metaclasses that have
be7677c7 102 # been initialized thus far (for mugwumps obj browser)
1d68af04 103 sub get_all_metaclasses { %METAS }
104 sub get_all_metaclass_instances { values %METAS }
105 sub get_all_metaclass_names { keys %METAS }
be7677c7 106 sub get_metaclass_by_name { $METAS{$_[0]} }
1d68af04 107 sub store_metaclass_by_name { $METAS{$_[0]} = $_[1] }
108 sub weaken_metaclass { weaken($METAS{$_[0]}) }
be7677c7 109 sub does_metaclass_exist { exists $METAS{$_[0]} && defined $METAS{$_[0]} }
1d68af04 110 sub remove_metaclass_by_name { $METAS{$_[0]} = undef }
111
be7677c7 112 # NOTE:
1d68af04 113 # We only cache metaclasses, meaning instances of
114 # Class::MOP::Class. We do not cache instance of
be7677c7 115 # Class::MOP::Package or Class::MOP::Module. Mostly
1d68af04 116 # because I don't yet see a good reason to do so.
be7677c7 117}
118
448b6e55 119sub load_class {
120 my $class = shift;
ab5e2f48 121
122 if (ref($class) || !defined($class) || !length($class)) {
123 my $display = defined($class) ? $class : 'undef';
124 confess "Invalid class name ($display)";
125 }
126
07940968 127 # if the class is not already loaded in the symbol table..
128 unless (is_class_loaded($class)) {
129 # require it
130 my $file = $class . '.pm';
131 $file =~ s{::}{/}g;
132 eval { CORE::require($file) };
133 confess "Could not load class ($class) because : $@" if $@;
134 }
135
136 # initialize a metaclass if necessary
448b6e55 137 unless (does_metaclass_exist($class)) {
138 eval { Class::MOP::Class->initialize($class) };
1d68af04 139 confess "Could not initialize class ($class) because : $@" if $@;
448b6e55 140 }
07940968 141
142 return get_metaclass_by_name($class);
448b6e55 143}
144
145sub is_class_loaded {
c1d5345a 146 my $class = shift;
26fcef27 147
148 return 0 if ref($class) || !defined($class) || !length($class);
149
150 # walk the symbol table tree to avoid autovififying
151 # \*{${main::}{"Foo::"}} == \*main::Foo::
152
153 my $pack = \*::;
154 foreach my $part (split('::', $class)) {
155 return 0 unless exists ${$$pack}{"${part}::"};
156 $pack = \*{${$$pack}{"${part}::"}};
c1d5345a 157 }
26fcef27 158
159 # check for $VERSION or @ISA
160 return 1 if exists ${$$pack}{VERSION}
161 && defined *{${$$pack}{VERSION}}{SCALAR};
162 return 1 if exists ${$$pack}{ISA}
163 && defined *{${$$pack}{ISA}}{ARRAY};
164
165 # check for any method
166 foreach ( keys %{$$pack} ) {
167 next if substr($_, -2, 2) eq '::';
d5be3722 168
169 my $glob = ${$$pack}{$_} || next;
170
9e275e86 171 # constant subs
d5be3722 172 if ( IS_RUNNING_ON_5_10 ) {
173 return 1 if ref $glob eq 'SCALAR';
174 }
175
176 return 1 if defined *{$glob}{CODE};
26fcef27 177 }
178
179 # fail
c1d5345a 180 return 0;
448b6e55 181}
182
183
aa448b16 184## ----------------------------------------------------------------------------
185## Setting up our environment ...
186## ----------------------------------------------------------------------------
1d68af04 187## Class::MOP needs to have a few things in the global perl environment so
aa448b16 188## that it can operate effectively. Those things are done here.
189## ----------------------------------------------------------------------------
190
3bf7644b 191# ... nothing yet actually ;)
8b978dd5 192
b51af7f9 193## ----------------------------------------------------------------------------
1d68af04 194## Bootstrapping
b51af7f9 195## ----------------------------------------------------------------------------
1d68af04 196## The code below here is to bootstrap our MOP with itself. This is also
b51af7f9 197## sometimes called "tying the knot". By doing this, we make it much easier
198## to extend the MOP through subclassing and such since now you can use the
1d68af04 199## MOP itself to extend itself.
200##
b51af7f9 201## Yes, I know, thats weird and insane, but it's a good thing, trust me :)
1d68af04 202## ----------------------------------------------------------------------------
727919c5 203
1d68af04 204# We need to add in the meta-attributes here so that
205# any subclass of Class::MOP::* will be able to
727919c5 206# inherit them using &construct_instance
207
f0480c45 208## --------------------------------------------------------
6d5355c3 209## Class::MOP::Package
727919c5 210
6d5355c3 211Class::MOP::Package->meta->add_attribute(
8683db0e 212 Class::MOP::Attribute->new('package' => (
b880e0de 213 reader => {
1d68af04 214 # NOTE: we need to do this in order
215 # for the instance meta-object to
b880e0de 216 # not fall into meta-circular death
1d68af04 217 #
ce2ae40f 218 # we just alias the original method
1d68af04 219 # rather than re-produce it here
ce2ae40f 220 'name' => \&Class::MOP::Package::name
b880e0de 221 },
c23184fc 222 init_arg => 'package',
727919c5 223 ))
224);
225
a5e51f0b 226Class::MOP::Package->meta->add_attribute(
8683db0e 227 Class::MOP::Attribute->new('namespace' => (
a5e51f0b 228 reader => {
56dcfc1a 229 # NOTE:
ce2ae40f 230 # we just alias the original method
231 # rather than re-produce it here
232 'namespace' => \&Class::MOP::Package::namespace
a5e51f0b 233 },
2e877f58 234 init_arg => undef,
c4260b45 235 default => sub { \undef }
a5e51f0b 236 ))
237);
238
9d6dce77 239# NOTE:
240# use the metaclass to construct the meta-package
241# which is a superclass of the metaclass itself :P
242Class::MOP::Package->meta->add_method('initialize' => sub {
243 my $class = shift;
244 my $package_name = shift;
1d68af04 245 $class->meta->new_object('package' => $package_name, @_);
9d6dce77 246});
247
f0480c45 248## --------------------------------------------------------
249## Class::MOP::Module
250
251# NOTE:
1d68af04 252# yeah this is kind of stretching things a bit,
f0480c45 253# but truthfully the version should be an attribute
1d68af04 254# of the Module, the weirdness comes from having to
255# stick to Perl 5 convention and store it in the
256# $VERSION package variable. Basically if you just
257# squint at it, it will look how you want it to look.
f0480c45 258# Either as a package variable, or as a attribute of
259# the metaclass, isn't abstraction great :)
260
261Class::MOP::Module->meta->add_attribute(
8683db0e 262 Class::MOP::Attribute->new('version' => (
f0480c45 263 reader => {
ce2ae40f 264 # NOTE:
265 # we just alias the original method
1d68af04 266 # rather than re-produce it here
ce2ae40f 267 'version' => \&Class::MOP::Module::version
f0480c45 268 },
2e877f58 269 init_arg => undef,
c4260b45 270 default => sub { \undef }
f0480c45 271 ))
272);
273
274# NOTE:
1d68af04 275# By following the same conventions as version here,
276# we are opening up the possibility that people can
277# use the $AUTHORITY in non-Class::MOP modules as
278# well.
f0480c45 279
280Class::MOP::Module->meta->add_attribute(
8683db0e 281 Class::MOP::Attribute->new('authority' => (
f0480c45 282 reader => {
ce2ae40f 283 # NOTE:
284 # we just alias the original method
1d68af04 285 # rather than re-produce it here
ce2ae40f 286 'authority' => \&Class::MOP::Module::authority
1d68af04 287 },
2e877f58 288 init_arg => undef,
c4260b45 289 default => sub { \undef }
f0480c45 290 ))
291);
292
293## --------------------------------------------------------
6d5355c3 294## Class::MOP::Class
295
727919c5 296Class::MOP::Class->meta->add_attribute(
8683db0e 297 Class::MOP::Attribute->new('attributes' => (
f7259199 298 reader => {
1d68af04 299 # NOTE: we need to do this in order
300 # for the instance meta-object to
301 # not fall into meta-circular death
302 #
ce2ae40f 303 # we just alias the original method
1d68af04 304 # rather than re-produce it here
ce2ae40f 305 'get_attribute_map' => \&Class::MOP::Class::get_attribute_map
f7259199 306 },
c23184fc 307 init_arg => 'attributes',
727919c5 308 default => sub { {} }
309 ))
310);
311
351bd7d4 312Class::MOP::Class->meta->add_attribute(
8683db0e 313 Class::MOP::Attribute->new('methods' => (
c23184fc 314 init_arg => 'methods',
1d68af04 315 reader => {
ce2ae40f 316 # NOTE:
317 # we just alias the original method
1d68af04 318 # rather than re-produce it here
ce2ae40f 319 'get_method_map' => \&Class::MOP::Class::get_method_map
92330ee2 320 },
7855ddba 321 default => sub { {} }
c4260b45 322 ))
323);
324
325Class::MOP::Class->meta->add_attribute(
8683db0e 326 Class::MOP::Attribute->new('superclasses' => (
c23184fc 327 accessor => {
328 # NOTE:
329 # we just alias the original method
1d68af04 330 # rather than re-produce it here
c23184fc 331 'superclasses' => \&Class::MOP::Class::superclasses
332 },
2e877f58 333 init_arg => undef,
c23184fc 334 default => sub { \undef }
335 ))
336);
337
338Class::MOP::Class->meta->add_attribute(
8683db0e 339 Class::MOP::Attribute->new('attribute_metaclass' => (
1d68af04 340 reader => {
6d2118a4 341 # NOTE:
342 # we just alias the original method
1d68af04 343 # rather than re-produce it here
6d2118a4 344 'attribute_metaclass' => \&Class::MOP::Class::attribute_metaclass
1d68af04 345 },
c23184fc 346 init_arg => 'attribute_metaclass',
351bd7d4 347 default => 'Class::MOP::Attribute',
348 ))
349);
350
351Class::MOP::Class->meta->add_attribute(
8683db0e 352 Class::MOP::Attribute->new('method_metaclass' => (
1d68af04 353 reader => {
6d2118a4 354 # NOTE:
355 # we just alias the original method
1d68af04 356 # rather than re-produce it here
6d2118a4 357 'method_metaclass' => \&Class::MOP::Class::method_metaclass
358 },
c23184fc 359 init_arg => 'method_metaclass',
1d68af04 360 default => 'Class::MOP::Method',
351bd7d4 361 ))
362);
363
2bab2be6 364Class::MOP::Class->meta->add_attribute(
8683db0e 365 Class::MOP::Attribute->new('instance_metaclass' => (
b880e0de 366 reader => {
1d68af04 367 # NOTE: we need to do this in order
368 # for the instance meta-object to
369 # not fall into meta-circular death
370 #
ce2ae40f 371 # we just alias the original method
1d68af04 372 # rather than re-produce it here
ce2ae40f 373 'instance_metaclass' => \&Class::MOP::Class::instance_metaclass
b880e0de 374 },
c23184fc 375 init_arg => 'instance_metaclass',
1d68af04 376 default => 'Class::MOP::Instance',
2bab2be6 377 ))
378);
379
9d6dce77 380# NOTE:
1d68af04 381# we don't actually need to tie the knot with
382# Class::MOP::Class here, it is actually handled
383# within Class::MOP::Class itself in the
384# construct_class_instance method.
9d6dce77 385
f0480c45 386## --------------------------------------------------------
727919c5 387## Class::MOP::Attribute
388
7b31baf4 389Class::MOP::Attribute->meta->add_attribute(
8683db0e 390 Class::MOP::Attribute->new('name' => (
c23184fc 391 init_arg => 'name',
392 reader => {
1d68af04 393 # NOTE: we need to do this in order
394 # for the instance meta-object to
395 # not fall into meta-circular death
396 #
ce2ae40f 397 # we just alias the original method
1d68af04 398 # rather than re-produce it here
ce2ae40f 399 'name' => \&Class::MOP::Attribute::name
b880e0de 400 }
7b31baf4 401 ))
402);
403
404Class::MOP::Attribute->meta->add_attribute(
8683db0e 405 Class::MOP::Attribute->new('associated_class' => (
c23184fc 406 init_arg => 'associated_class',
407 reader => {
1d68af04 408 # NOTE: we need to do this in order
409 # for the instance meta-object to
410 # not fall into meta-circular death
411 #
ce2ae40f 412 # we just alias the original method
1d68af04 413 # rather than re-produce it here
ce2ae40f 414 'associated_class' => \&Class::MOP::Attribute::associated_class
b880e0de 415 }
7b31baf4 416 ))
417);
418
419Class::MOP::Attribute->meta->add_attribute(
8683db0e 420 Class::MOP::Attribute->new('accessor' => (
c23184fc 421 init_arg => 'accessor',
6d2118a4 422 reader => { 'accessor' => \&Class::MOP::Attribute::accessor },
423 predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor },
7b31baf4 424 ))
425);
426
427Class::MOP::Attribute->meta->add_attribute(
8683db0e 428 Class::MOP::Attribute->new('reader' => (
c23184fc 429 init_arg => 'reader',
6d2118a4 430 reader => { 'reader' => \&Class::MOP::Attribute::reader },
431 predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader },
7b31baf4 432 ))
433);
434
435Class::MOP::Attribute->meta->add_attribute(
8683db0e 436 Class::MOP::Attribute->new('initializer' => (
0ab65f99 437 init_arg => 'initializer',
8ee74136 438 reader => { 'initializer' => \&Class::MOP::Attribute::initializer },
439 predicate => { 'has_initializer' => \&Class::MOP::Attribute::has_initializer },
0ab65f99 440 ))
441);
442
443Class::MOP::Attribute->meta->add_attribute(
8683db0e 444 Class::MOP::Attribute->new('writer' => (
c23184fc 445 init_arg => 'writer',
6d2118a4 446 reader => { 'writer' => \&Class::MOP::Attribute::writer },
447 predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer },
7b31baf4 448 ))
449);
450
451Class::MOP::Attribute->meta->add_attribute(
8683db0e 452 Class::MOP::Attribute->new('predicate' => (
c23184fc 453 init_arg => 'predicate',
6d2118a4 454 reader => { 'predicate' => \&Class::MOP::Attribute::predicate },
455 predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate },
7b31baf4 456 ))
457);
458
459Class::MOP::Attribute->meta->add_attribute(
8683db0e 460 Class::MOP::Attribute->new('clearer' => (
c23184fc 461 init_arg => 'clearer',
6d2118a4 462 reader => { 'clearer' => \&Class::MOP::Attribute::clearer },
463 predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer },
7d28758b 464 ))
465);
466
467Class::MOP::Attribute->meta->add_attribute(
8683db0e 468 Class::MOP::Attribute->new('builder' => (
1d68af04 469 init_arg => 'builder',
470 reader => { 'builder' => \&Class::MOP::Attribute::builder },
471 predicate => { 'has_builder' => \&Class::MOP::Attribute::has_builder },
472 ))
473);
474
475Class::MOP::Attribute->meta->add_attribute(
8683db0e 476 Class::MOP::Attribute->new('init_arg' => (
c23184fc 477 init_arg => 'init_arg',
6d2118a4 478 reader => { 'init_arg' => \&Class::MOP::Attribute::init_arg },
479 predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg },
7b31baf4 480 ))
481);
482
483Class::MOP::Attribute->meta->add_attribute(
8683db0e 484 Class::MOP::Attribute->new('default' => (
c23184fc 485 init_arg => 'default',
7b31baf4 486 # default has a custom 'reader' method ...
1d68af04 487 predicate => { 'has_default' => \&Class::MOP::Attribute::has_default },
7b31baf4 488 ))
489);
490
3545c727 491Class::MOP::Attribute->meta->add_attribute(
8683db0e 492 Class::MOP::Attribute->new('associated_methods' => (
c23184fc 493 init_arg => 'associated_methods',
494 reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
1d68af04 495 default => sub { [] }
3545c727 496 ))
497);
727919c5 498
499# NOTE: (meta-circularity)
500# This should be one of the last things done
501# it will "tie the knot" with Class::MOP::Attribute
1d68af04 502# so that it uses the attributes meta-objects
503# to construct itself.
727919c5 504Class::MOP::Attribute->meta->add_method('new' => sub {
649efb63 505 my ( $class, @args ) = @_;
506
507 unshift @args, "name" if @args % 2 == 1;
508 my %options = @args;
509
510 my $name = $options{name};
1d68af04 511
727919c5 512 (defined $name && $name)
513 || confess "You must provide a name for the attribute";
1d68af04 514 $options{init_arg} = $name
5659d76e 515 if not exists $options{init_arg};
1d68af04 516
517 if(exists $options{builder}){
518 confess("builder must be a defined scalar value which is a method name")
519 if ref $options{builder} || !(defined $options{builder});
520 confess("Setting both default and builder is not allowed.")
521 if exists $options{default};
8fe581e5 522 } else {
523 (Class::MOP::Attribute::is_default_a_coderef(\%options))
524 || confess("References are not allowed as default values, you must ".
3c0a8087 525 "wrap the default of '$name' in a CODE reference (ex: sub { [] } and not [])")
8fe581e5 526 if exists $options{default} && ref $options{default};
1d68af04 527 }
8683db0e 528
5659d76e 529 # return the new object
649efb63 530 $class->meta->new_object(%options);
5659d76e 531});
532
533Class::MOP::Attribute->meta->add_method('clone' => sub {
a740253a 534 my $self = shift;
1d68af04 535 $self->meta->clone_object($self, @_);
727919c5 536});
537
f0480c45 538## --------------------------------------------------------
b6164407 539## Class::MOP::Method
b6164407 540Class::MOP::Method->meta->add_attribute(
8683db0e 541 Class::MOP::Attribute->new('body' => (
c23184fc 542 init_arg => 'body',
543 reader => { 'body' => \&Class::MOP::Method::body },
b6164407 544 ))
545);
546
4c105333 547Class::MOP::Method->meta->add_attribute(
8683db0e 548 Class::MOP::Attribute->new('package_name' => (
4c105333 549 init_arg => 'package_name',
550 reader => { 'package_name' => \&Class::MOP::Method::package_name },
551 ))
552);
553
554Class::MOP::Method->meta->add_attribute(
8683db0e 555 Class::MOP::Attribute->new('name' => (
4c105333 556 init_arg => 'name',
557 reader => { 'name' => \&Class::MOP::Method::name },
558 ))
559);
560
561Class::MOP::Method->meta->add_method('wrap' => sub {
5caf45ce 562 my ( $class, @args ) = @_;
563
564 unshift @args, 'body' if @args % 2 == 1;
565
566 my %options = @args;
567 my $code = $options{body};
4c105333 568
9b522fc4 569 ('CODE' eq ref($code))
4c105333 570 || confess "You must supply a CODE reference to bless, not (" . ($code || 'undef') . ")";
571
b38f3848 572 ($options{package_name} && $options{name})
573 || confess "You must supply the package_name and name parameters";
574
4c105333 575 # return the new object
5caf45ce 576 $class->meta->new_object(%options);
4c105333 577});
578
579Class::MOP::Method->meta->add_method('clone' => sub {
580 my $self = shift;
581 $self->meta->clone_object($self, @_);
582});
583
b6164407 584## --------------------------------------------------------
585## Class::MOP::Method::Wrapped
586
587# NOTE:
1d68af04 588# the way this item is initialized, this
589# really does not follow the standard
590# practices of attributes, but we put
b6164407 591# it here for completeness
592Class::MOP::Method::Wrapped->meta->add_attribute(
8683db0e 593 Class::MOP::Attribute->new('modifier_table')
b6164407 594);
595
596## --------------------------------------------------------
565f0cbb 597## Class::MOP::Method::Generated
598
599Class::MOP::Method::Generated->meta->add_attribute(
8683db0e 600 Class::MOP::Attribute->new('is_inline' => (
565f0cbb 601 init_arg => 'is_inline',
602 reader => { 'is_inline' => \&Class::MOP::Method::Generated::is_inline },
4c105333 603 default => 0,
1d68af04 604 ))
565f0cbb 605);
606
4c105333 607Class::MOP::Method::Generated->meta->add_method('new' => sub {
608 my ($class, %options) = @_;
b38f3848 609 ($options{package_name} && $options{name})
610 || confess "You must supply the package_name and name parameters";
4c105333 611 my $self = $class->meta->new_object(%options);
612 $self->initialize_body;
613 $self;
614});
615
565f0cbb 616## --------------------------------------------------------
d90b42a6 617## Class::MOP::Method::Accessor
618
619Class::MOP::Method::Accessor->meta->add_attribute(
8683db0e 620 Class::MOP::Attribute->new('attribute' => (
c23184fc 621 init_arg => 'attribute',
1d68af04 622 reader => {
623 'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute
d90b42a6 624 },
1d68af04 625 ))
d90b42a6 626);
627
628Class::MOP::Method::Accessor->meta->add_attribute(
8683db0e 629 Class::MOP::Attribute->new('accessor_type' => (
c23184fc 630 init_arg => 'accessor_type',
631 reader => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
1d68af04 632 ))
d90b42a6 633);
634
4c105333 635Class::MOP::Method::Accessor->meta->add_method('new' => sub {
636 my $class = shift;
637 my %options = @_;
638
639 (exists $options{attribute})
640 || confess "You must supply an attribute to construct with";
641
642 (exists $options{accessor_type})
643 || confess "You must supply an accessor_type to construct with";
644
645 (Scalar::Util::blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
646 || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance";
647
b38f3848 648 ($options{package_name} && $options{name})
649 || confess "You must supply the package_name and name parameters";
650
4c105333 651 # return the new object
652 my $self = $class->meta->new_object(%options);
653
654 # we don't want this creating
655 # a cycle in the code, if not
656 # needed
8683db0e 657 Scalar::Util::weaken($self->{'attribute'});
4c105333 658
659 $self->initialize_body;
660
661 $self;
662});
663
d90b42a6 664
665## --------------------------------------------------------
666## Class::MOP::Method::Constructor
667
668Class::MOP::Method::Constructor->meta->add_attribute(
8683db0e 669 Class::MOP::Attribute->new('options' => (
c23184fc 670 init_arg => 'options',
1d68af04 671 reader => {
672 'options' => \&Class::MOP::Method::Constructor::options
d90b42a6 673 },
4c105333 674 default => sub { +{} }
1d68af04 675 ))
d90b42a6 676);
677
678Class::MOP::Method::Constructor->meta->add_attribute(
8683db0e 679 Class::MOP::Attribute->new('associated_metaclass' => (
c23184fc 680 init_arg => 'metaclass',
1d68af04 681 reader => {
682 'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass
683 },
684 ))
d90b42a6 685);
686
4c105333 687Class::MOP::Method::Constructor->meta->add_method('new' => sub {
688 my $class = shift;
689 my %options = @_;
690
691 (Scalar::Util::blessed $options{metaclass} && $options{metaclass}->isa('Class::MOP::Class'))
692 || confess "You must pass a metaclass instance if you want to inline"
693 if $options{is_inline};
694
b38f3848 695 ($options{package_name} && $options{name})
696 || confess "You must supply the package_name and name parameters";
697
4c105333 698 # return the new object
699 my $self = $class->meta->new_object(%options);
700
701 # we don't want this creating
702 # a cycle in the code, if not
703 # needed
8683db0e 704 Scalar::Util::weaken($self->{'associated_metaclass'});
4c105333 705
706 $self->initialize_body;
707
708 $self;
709});
710
d90b42a6 711## --------------------------------------------------------
86482605 712## Class::MOP::Instance
713
714# NOTE:
1d68af04 715# these don't yet do much of anything, but are just
86482605 716# included for completeness
717
718Class::MOP::Instance->meta->add_attribute(
63d08a9e 719 Class::MOP::Attribute->new('associated_metaclass')
86482605 720);
721
722Class::MOP::Instance->meta->add_attribute(
32bfc810 723 Class::MOP::Attribute->new('attributes')
724);
725
726Class::MOP::Instance->meta->add_attribute(
8683db0e 727 Class::MOP::Attribute->new('slots')
86482605 728);
729
63d08a9e 730Class::MOP::Instance->meta->add_attribute(
731 Class::MOP::Attribute->new('slot_hash')
732);
733
734
caa051fa 735# we need the meta instance of the meta instance to be created now, in order
736# for the constructor to be able to use it
737Class::MOP::Instance->meta->get_meta_instance;
738
739Class::MOP::Instance->meta->add_method('new' => sub {
740 my $class = shift;
741 my $options = $class->BUILDARGS(@_);
742
743 my $self = $class->meta->new_object(%$options);
744
745 Scalar::Util::weaken($self->{'associated_metaclass'});
746
747 $self;
748});
749
750# pretend the add_method never happenned. it hasn't yet affected anything
751undef Class::MOP::Instance->meta->{_package_cache_flag};
752
86482605 753## --------------------------------------------------------
f0480c45 754## Now close all the Class::MOP::* classes
4d47b77f 755
0b9372a2 756# NOTE:
1d68af04 757# we don't need to inline the
758# constructors or the accessors
759# this only lengthens the compile
760# time of the MOP, and gives us
0b9372a2 761# no actual benefits.
762
763$_->meta->make_immutable(
764 inline_constructor => 0,
765 inline_accessors => 0,
766) for qw/
1d68af04 767 Class::MOP::Package
768 Class::MOP::Module
769 Class::MOP::Class
770
0b9372a2 771 Class::MOP::Attribute
1d68af04 772 Class::MOP::Method
773 Class::MOP::Instance
774
775 Class::MOP::Object
0b9372a2 776
565f0cbb 777 Class::MOP::Method::Generated
1d68af04 778
ba38bf08 779 Class::MOP::Method::Accessor
1d68af04 780 Class::MOP::Method::Constructor
781 Class::MOP::Method::Wrapped
0b9372a2 782/;
b6164407 783
94b19069 7841;
785
786__END__
787
788=pod
789
1d68af04 790=head1 NAME
94b19069 791
792Class::MOP - A Meta Object Protocol for Perl 5
793
94b19069 794=head1 DESCRIPTON
795
127d39a7 796This module is a fully functioning meta object protocol for the
1d68af04 797Perl 5 object system. It makes no attempt to change the behavior or
798characteristics of the Perl 5 object system, only to create a
27e31eaf 799protocol for its manipulation and introspection.
94b19069 800
1d68af04 801That said, it does attempt to create the tools for building a rich
802set of extensions to the Perl 5 object system. Every attempt has been
803made for these tools to keep to the spirit of the Perl 5 object
94b19069 804system that we all know and love.
805
1d68af04 806This documentation is admittedly sparse on details, as time permits
807I will try to improve them. For now, I suggest looking at the items
808listed in the L<SEE ALSO> section for more information. In particular
809the book "The Art of the Meta Object Protocol" was very influential
40483095 810in the development of this system.
811
bfe4d0fc 812=head2 What is a Meta Object Protocol?
813
1d68af04 814A meta object protocol is an API to an object system.
bfe4d0fc 815
1d68af04 816To be more specific, it is a set of abstractions of the components of
817an object system (typically things like; classes, object, methods,
818object attributes, etc.). These abstractions can then be used to both
bfe4d0fc 819inspect and manipulate the object system which they describe.
820
1d68af04 821It can be said that there are two MOPs for any object system; the
822implicit MOP, and the explicit MOP. The implicit MOP handles things
823like method dispatch or inheritance, which happen automatically as
824part of how the object system works. The explicit MOP typically
825handles the introspection/reflection features of the object system.
826All object systems have implicit MOPs, without one, they would not
827work. Explict MOPs however as less common, and depending on the
828language can vary from restrictive (Reflection in Java or C#) to
829wide open (CLOS is a perfect example).
bfe4d0fc 830
e16da3e6 831=head2 Yet Another Class Builder!! Why?
832
1d68af04 833This is B<not> a class builder so much as it is a I<class builder
834B<builder>>. My intent is that an end user does not use this module
835directly, but instead this module is used by module authors to
836build extensions and features onto the Perl 5 object system.
e16da3e6 837
94b19069 838=head2 Who is this module for?
839
1d68af04 840This module is specifically for anyone who has ever created or
841wanted to create a module for the Class:: namespace. The tools which
842this module will provide will hopefully make it easier to do more
843complex things with Perl 5 classes by removing such barriers as
844the need to hack the symbol tables, or understand the fine details
845of method dispatch.
94b19069 846
bfe4d0fc 847=head2 What changes do I have to make to use this module?
848
1d68af04 849This module was designed to be as unintrusive as possible. Many of
850its features are accessible without B<any> change to your existsing
851code at all. It is meant to be a compliment to your existing code and
852not an intrusion on your code base. Unlike many other B<Class::>
853modules, this module B<does not> require you subclass it, or even that
854you C<use> it in within your module's package.
bfe4d0fc 855
1d68af04 856The only features which requires additions to your code are the
2eb717d5 857attribute handling and instance construction features, and these are
1d68af04 858both completely optional features. The only reason for this is because
859Perl 5's object system does not actually have these features built
2eb717d5 860in. More information about this feature can be found below.
bfe4d0fc 861
862=head2 A Note about Performance?
863
1d68af04 864It is a common misconception that explict MOPs are performance drains.
865But this is not a universal truth at all, it is an side-effect of
866specific implementations. For instance, using Java reflection is much
867slower because the JVM cannot take advantage of any compiler
868optimizations, and the JVM has to deal with much more runtime type
869information as well. Reflection in C# is marginally better as it was
870designed into the language and runtime (the CLR). In contrast, CLOS
871(the Common Lisp Object System) was built to support an explicit MOP,
872and so performance is tuned for it.
873
874This library in particular does it's absolute best to avoid putting
875B<any> drain at all upon your code's performance. In fact, by itself
876it does nothing to affect your existing code. So you only pay for
2eb717d5 877what you actually use.
bfe4d0fc 878
550d56db 879=head2 About Metaclass compatibility
880
1d68af04 881This module makes sure that all metaclasses created are both upwards
882and downwards compatible. The topic of metaclass compatibility is
883highly esoteric and is something only encountered when doing deep and
884involved metaclass hacking. There are two basic kinds of metaclass
885incompatibility; upwards and downwards.
550d56db 886
1d68af04 887Upwards metaclass compatibility means that the metaclass of a
888given class is either the same as (or a subclass of) all of the
550d56db 889class's ancestors.
890
1d68af04 891Downward metaclass compatibility means that the metaclasses of a
892given class's anscestors are all either the same as (or a subclass
550d56db 893of) that metaclass.
894
1d68af04 895Here is a diagram showing a set of two classes (C<A> and C<B>) and
896two metaclasses (C<Meta::A> and C<Meta::B>) which have correct
550d56db 897metaclass compatibility both upwards and downwards.
898
899 +---------+ +---------+
900 | Meta::A |<----| Meta::B | <....... (instance of )
1d68af04 901 +---------+ +---------+ <------- (inherits from)
550d56db 902 ^ ^
903 : :
904 +---------+ +---------+
905 | A |<----| B |
906 +---------+ +---------+
907
1d68af04 908As I said this is a highly esoteric topic and one you will only run
909into if you do a lot of subclassing of B<Class::MOP::Class>. If you
910are interested in why this is an issue see the paper
911I<Uniform and safe metaclass composition> linked to in the
550d56db 912L<SEE ALSO> section of this document.
913
aa448b16 914=head2 Using custom metaclasses
915
1d68af04 916Always use the metaclass pragma when using a custom metaclass, this
917will ensure the proper initialization order and not accidentely
918create an incorrect type of metaclass for you. This is a very rare
919problem, and one which can only occur if you are doing deep metaclass
aa448b16 920programming. So in other words, don't worry about it.
921
94b19069 922=head1 PROTOCOLS
923
127d39a7 924The protocol is divided into 4 main sub-protocols:
94b19069 925
926=over 4
927
928=item The Class protocol
929
1d68af04 930This provides a means of manipulating and introspecting a Perl 5
931class. It handles all of symbol table hacking for you, and provides
94b19069 932a rich set of methods that go beyond simple package introspection.
933
552e3d24 934See L<Class::MOP::Class> for more details.
935
94b19069 936=item The Attribute protocol
937
1d68af04 938This provides a consistent represenation for an attribute of a
939Perl 5 class. Since there are so many ways to create and handle
127d39a7 940attributes in Perl 5 OO, this attempts to provide as much of a
1d68af04 941unified approach as possible, while giving the freedom and
94b19069 942flexibility to subclass for specialization.
943
552e3d24 944See L<Class::MOP::Attribute> for more details.
945
94b19069 946=item The Method protocol
947
1d68af04 948This provides a means of manipulating and introspecting methods in
949the Perl 5 object system. As with attributes, there are many ways to
950approach this topic, so we try to keep it pretty basic, while still
94b19069 951making it possible to extend the system in many ways.
952
552e3d24 953See L<Class::MOP::Method> for more details.
94b19069 954
127d39a7 955=item The Instance protocol
956
957This provides a layer of abstraction for creating object instances.
958Since the other layers use this protocol, it is relatively easy to
959change the type of your instances from the default HASH ref to other
960types of references. Several examples are provided in the F<examples/>
961directory included in this distribution.
962
963See L<Class::MOP::Instance> for more details.
964
94b19069 965=back
966
be7677c7 967=head1 FUNCTIONS
968
c1d5345a 969=head2 Constants
970
971=over 4
972
973=item I<IS_RUNNING_ON_5_10>
974
975We set this constant depending on what version perl we are on, this
976allows us to take advantage of new 5.10 features and stay backwards
977compat.
978
9efe16ca 979=item I<HAVE_ISAREV>
980
981Whether or not C<mro> provides C<get_isarev>, a much faster way to get all the
982subclasses of a certain class.
983
c1d5345a 984=back
985
448b6e55 986=head2 Utility functions
987
988=over 4
989
990=item B<load_class ($class_name)>
991
1d68af04 992This will load a given C<$class_name> and if it does not have an
448b6e55 993already initialized metaclass, then it will intialize one for it.
127d39a7 994This function can be used in place of tricks like
995C<eval "use $module"> or using C<require>.
448b6e55 996
997=item B<is_class_loaded ($class_name)>
998
1d68af04 999This will return a boolean depending on if the C<$class_name> has
1000been loaded.
448b6e55 1001
1d68af04 1002NOTE: This does a basic check of the symbol table to try and
448b6e55 1003determine as best it can if the C<$class_name> is loaded, it
1d68af04 1004is probably correct about 99% of the time.
448b6e55 1005
b1f5f41d 1006=item B<check_package_cache_flag ($pkg)>
e0e4674a 1007
127d39a7 1008This will return an integer that is managed by C<Class::MOP::Class>
1009to determine if a module's symbol table has been altered.
1010
1011In Perl 5.10 or greater, this flag is package specific. However in
1012versions prior to 5.10, this will use the C<PL_sub_generation> variable
1013which is not package specific.
1014
e0e4674a 1015=item B<get_code_info ($code)>
1016
127d39a7 1017This function returns two values, the name of the package the C<$code>
1018is from and the name of the C<$code> itself. This is used by several
1019elements of the MOP to detemine where a given C<$code> reference is from.
1020
4c105333 1021=item B<subname ($name, $code)>
1022
1023B<NOTE: DO NOT USE THIS FUNCTION, IT IS FOR INTERNAL USE ONLY!>
1024
1025If possible, we will load the L<Sub::Name> module and this will function
1026as C<Sub::Name::subname> does, otherwise it will just return the C<$code>
1027argument.
1028
448b6e55 1029=back
1030
1031=head2 Metaclass cache functions
1032
1d68af04 1033Class::MOP holds a cache of metaclasses, the following are functions
1034(B<not methods>) which can be used to access that cache. It is not
1035recommended that you mess with this, bad things could happen. But if
be7677c7 1036you are brave and willing to risk it, go for it.
1037
1038=over 4
1039
1040=item B<get_all_metaclasses>
1041
1d68af04 1042This will return an hash of all the metaclass instances that have
1043been cached by B<Class::MOP::Class> keyed by the package name.
b9d9fc0b 1044
be7677c7 1045=item B<get_all_metaclass_instances>
1046
1d68af04 1047This will return an array of all the metaclass instances that have
b9d9fc0b 1048been cached by B<Class::MOP::Class>.
1049
be7677c7 1050=item B<get_all_metaclass_names>
1051
1d68af04 1052This will return an array of all the metaclass names that have
b9d9fc0b 1053been cached by B<Class::MOP::Class>.
1054
be7677c7 1055=item B<get_metaclass_by_name ($name)>
1056
127d39a7 1057This will return a cached B<Class::MOP::Class> instance of nothing
1058if no metaclass exist by that C<$name>.
1059
be7677c7 1060=item B<store_metaclass_by_name ($name, $meta)>
1061
127d39a7 1062This will store a metaclass in the cache at the supplied C<$key>.
1063
be7677c7 1064=item B<weaken_metaclass ($name)>
1065
127d39a7 1066In rare cases it is desireable to store a weakened reference in
1067the metaclass cache. This function will weaken the reference to
1068the metaclass stored in C<$name>.
1069
be7677c7 1070=item B<does_metaclass_exist ($name)>
1071
127d39a7 1072This will return true of there exists a metaclass stored in the
1073C<$name> key and return false otherwise.
1074
be7677c7 1075=item B<remove_metaclass_by_name ($name)>
1076
127d39a7 1077This will remove a the metaclass stored in the C<$name> key.
1078
be7677c7 1079=back
1080
552e3d24 1081=head1 SEE ALSO
8b978dd5 1082
552e3d24 1083=head2 Books
8b978dd5 1084
1d68af04 1085There are very few books out on Meta Object Protocols and Metaclasses
1086because it is such an esoteric topic. The following books are really
1087the only ones I have found. If you know of any more, B<I<please>>
a2e85e6c 1088email me and let me know, I would love to hear about them.
1089
8b978dd5 1090=over 4
1091
552e3d24 1092=item "The Art of the Meta Object Protocol"
8b978dd5 1093
552e3d24 1094=item "Advances in Object-Oriented Metalevel Architecture and Reflection"
8b978dd5 1095
b51af7f9 1096=item "Putting MetaClasses to Work"
1097
a2e85e6c 1098=item "Smalltalk: The Language"
1099
94b19069 1100=back
1101
550d56db 1102=head2 Papers
1103
1104=over 4
1105
1106=item Uniform and safe metaclass composition
1107
1d68af04 1108An excellent paper by the people who brought us the original Traits paper.
1109This paper is on how Traits can be used to do safe metaclass composition,
1110and offers an excellent introduction section which delves into the topic of
550d56db 1111metaclass compatibility.
1112
1113L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
1114
1115=item Safe Metaclass Programming
1116
1d68af04 1117This paper seems to precede the above paper, and propose a mix-in based
1118approach as opposed to the Traits based approach. Both papers have similar
1119information on the metaclass compatibility problem space.
550d56db 1120
1121L<http://citeseer.ist.psu.edu/37617.html>
1122
1123=back
1124
552e3d24 1125=head2 Prior Art
8b978dd5 1126
1127=over 4
1128
7184ca14 1129=item The Perl 6 MetaModel work in the Pugs project
8b978dd5 1130
1131=over 4
1132
552e3d24 1133=item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
8b978dd5 1134
552e3d24 1135=item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
8b978dd5 1136
1137=back
1138
94b19069 1139=back
1140
1d68af04 1141=head2 Articles
f8dfcfb7 1142
1143=over 4
1144
1d68af04 1145=item CPAN Module Review of Class::MOP
f8dfcfb7 1146
1147L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
1148
1149=back
1150
a2e85e6c 1151=head1 SIMILAR MODULES
1152
1d68af04 1153As I have said above, this module is a class-builder-builder, so it is
1154not the same thing as modules like L<Class::Accessor> and
1155L<Class::MethodMaker>. That being said there are very few modules on CPAN
1156with similar goals to this module. The one I have found which is most
1157like this module is L<Class::Meta>, although it's philosophy and the MOP it
1158creates are very different from this modules.
94b19069 1159
a2e85e6c 1160=head1 BUGS
1161
1d68af04 1162All complex software has bugs lurking in it, and this module is no
a2e85e6c 1163exception. If you find a bug please either email me, or add the bug
1164to cpan-RT.
1165
1166=head1 ACKNOWLEDGEMENTS
1167
1168=over 4
1169
b9d9fc0b 1170=item Rob Kinyon
a2e85e6c 1171
1d68af04 1172Thanks to Rob for actually getting the development of this module kick-started.
a2e85e6c 1173
1174=back
1175
1a09d9cc 1176=head1 AUTHORS
94b19069 1177
a2e85e6c 1178Stevan Little E<lt>stevan@iinteractive.comE<gt>
552e3d24 1179
9c8cda90 1180B<with contributions from:>
1181
1182Brandon (blblack) Black
1183
1184Guillermo (groditi) Roditi
1185
9195ddff 1186Matt (mst) Trout
1187
9c8cda90 1188Rob (robkinyon) Kinyon
1189
1190Yuval (nothingmuch) Kogman
1a09d9cc 1191
f430cfa4 1192Scott (konobi) McWhirter
1193
94b19069 1194=head1 COPYRIGHT AND LICENSE
1195
69e3ab0a 1196Copyright 2006-2008 by Infinity Interactive, Inc.
94b19069 1197
1198L<http://www.iinteractive.com>
1199
1200This library is free software; you can redistribute it and/or modify
1d68af04 1201it under the same terms as Perl itself.
94b19069 1202
1203=cut