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