setting weaken should be based on the passed in cache value
[gitmo/Moose.git] / lib / Class / MOP / Package.pm
CommitLineData
38bf2a25 1
2package Class::MOP::Package;
3
4use strict;
5use warnings;
6
0db1c8dc 7use Scalar::Util 'blessed', 'reftype', 'weaken';
38bf2a25 8use Carp 'confess';
0db1c8dc 9use Devel::GlobalDestruction 'in_global_destruction';
38bf2a25 10use Package::Stash;
11
38bf2a25 12use base 'Class::MOP::Object';
13
14# creation ...
15
16sub initialize {
17 my ( $class, @args ) = @_;
18
19 unshift @args, "package" if @args % 2;
20
21 my %options = @args;
0db1c8dc 22 my $package_name = delete $options{package};
38bf2a25 23
24
25 # we hand-construct the class
26 # until we can bootstrap it
27 if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
28 return $meta;
29 } else {
30 my $meta = ( ref $class || $class )->_new({
31 'package' => $package_name,
32 %options,
33 });
34 Class::MOP::store_metaclass_by_name($package_name, $meta);
35
0db1c8dc 36 Class::MOP::weaken_metaclass($package_name) if $options{weaken};
37
38
38bf2a25 39 return $meta;
40 }
41}
42
43sub reinitialize {
44 my ( $class, @args ) = @_;
45
46 unshift @args, "package" if @args % 2;
47
48 my %options = @args;
49 my $package_name = delete $options{package};
50
51 (defined $package_name && $package_name
52 && (!blessed $package_name || $package_name->isa('Class::MOP::Package')))
53 || confess "You must pass a package name or an existing Class::MOP::Package instance";
54
55 $package_name = $package_name->name
56 if blessed $package_name;
57
58 Class::MOP::remove_metaclass_by_name($package_name);
59
60 $class->initialize($package_name, %options); # call with first arg form for compat
61}
62
0db1c8dc 63sub create {
64 my $class = shift;
65 my @args = @_;
66
67 return $class->initialize(@args);
68}
69
70## ANON packages
71
72{
73 # NOTE:
74 # this should be sufficient, if you have a
75 # use case where it is not, write a test and
76 # I will change it.
77 my $ANON_SERIAL = 0;
78
79 my %ANON_PACKAGE_CACHE;
80
81 # NOTE:
82 # we need a sufficiently annoying prefix
83 # this should suffice for now, this is
84 # used in a couple of places below, so
85 # need to put it up here for now.
86 sub _anon_package_prefix { 'Class::MOP::Package::__ANON__::SERIAL::' }
87
88 sub is_anon {
89 my $self = shift;
90 no warnings 'uninitialized';
91 my $prefix = $self->_anon_package_prefix;
9520ee8e 92 $self->name =~ /^\Q$prefix/;
0db1c8dc 93 }
94
95 sub create_anon {
96 my ($class, %options) = @_;
97
98 my $cache_ok = delete $options{cache};
85db9063 99 $options{weaken} = !$cache_ok unless exists $options{weaken};
0db1c8dc 100
4f629382 101 my $cache_key;
102 if ($cache_ok) {
103 $cache_key = $class->_anon_cache_key(%options);
83dcb866 104 undef $cache_ok if !defined($cache_key);
105 }
0db1c8dc 106
83dcb866 107 if ($cache_ok) {
4f629382 108 if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
109 return $ANON_PACKAGE_CACHE{$cache_key};
110 }
0db1c8dc 111 }
112
0db1c8dc 113 my $package_name = $class->_anon_package_prefix . ++$ANON_SERIAL;
114
115 my $meta = $class->create($package_name, %options);
116
117 if ($cache_ok) {
118 $ANON_PACKAGE_CACHE{$cache_key} = $meta;
119 weaken($ANON_PACKAGE_CACHE{$cache_key});
120 }
121
122 return $meta;
123 }
124
125 sub _anon_cache_key { confess "Packages are not cacheable" }
126
127 sub DESTROY {
128 my $self = shift;
129
130 return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
131
132 $self->_free_anon
133 if $self->is_anon;
134 }
135
136 sub _free_anon {
137 my $self = shift;
138 my $name = $self->name;
139
140 # Moose does a weird thing where it replaces the metaclass for
141 # class when fixing metaclass incompatibility. In that case,
142 # we don't want to clean out the namespace now. We can detect
143 # that because Moose will explicitly update the singleton
144 # cache in Class::MOP.
145 no warnings 'uninitialized';
146 my $current_meta = Class::MOP::get_metaclass_by_name($name);
147 return if $current_meta ne $self;
148
149 my ($first_fragments, $last_fragment) = ($name =~ /^(.*)::(.*)$/);
150
151 no strict 'refs';
152 @{$name . '::ISA'} = ();
153 %{$name . '::'} = ();
154 delete ${$first_fragments . '::'}{$last_fragment . '::'};
155
156 Class::MOP::remove_metaclass_by_name($name);
157 }
158
159}
160
38bf2a25 161sub _new {
162 my $class = shift;
163
164 return Class::MOP::Class->initialize($class)->new_object(@_)
165 if $class ne __PACKAGE__;
166
167 my $params = @_ == 1 ? $_[0] : {@_};
168
169 return bless {
9c1bf11e 170 # Need to quote package to avoid a problem with PPI mis-parsing this
171 # as a package statement.
172 'package' => $params->{package},
38bf2a25 173
174 # NOTE:
175 # because of issues with the Perl API
176 # to the typeglob in some versions, we
177 # need to just always grab a new
178 # reference to the hash in the accessor.
179 # Ideally we could just store a ref and
180 # it would Just Work, but oh well :\
181
182 namespace => \undef,
183
184 } => $class;
185}
186
187# Attributes
188
189# NOTE:
190# all these attribute readers will be bootstrapped
191# away in the Class::MOP bootstrap section
192
193sub _package_stash {
194 $_[0]->{_package_stash} ||= Package::Stash->new($_[0]->name)
195}
196sub namespace {
197 $_[0]->_package_stash->namespace
198}
199
200# Class attributes
201
202# ... these functions have to touch the symbol table itself,.. yuk
203
204sub add_package_symbol {
205 my $self = shift;
206 $self->_package_stash->add_symbol(@_);
207}
208
209sub remove_package_glob {
210 my $self = shift;
211 $self->_package_stash->remove_glob(@_);
212}
213
214# ... these functions deal with stuff on the namespace level
215
216sub has_package_symbol {
217 my $self = shift;
218 $self->_package_stash->has_symbol(@_);
219}
220
221sub get_package_symbol {
222 my $self = shift;
223 $self->_package_stash->get_symbol(@_);
224}
225
226sub get_or_add_package_symbol {
227 my $self = shift;
228 $self->_package_stash->get_or_add_symbol(@_);
229}
230
231sub remove_package_symbol {
232 my $self = shift;
233 $self->_package_stash->remove_symbol(@_);
234}
235
236sub list_all_package_symbols {
237 my $self = shift;
238 $self->_package_stash->list_all_symbols(@_);
239}
240
241sub get_all_package_symbols {
242 my $self = shift;
243 $self->_package_stash->get_all_symbols(@_);
244}
245
2461;
247
248# ABSTRACT: Package Meta Object
249
250__END__
251
252=pod
253
254=head1 DESCRIPTION
255
256The Package Protocol provides an abstraction of a Perl 5 package. A
257package is basically namespace, and this module provides methods for
258looking at and changing that namespace's symbol table.
259
260=head1 METHODS
261
262=over 4
263
57272677 264=item B<< Class::MOP::Package->initialize($package_name, %options) >>
38bf2a25 265
266This method creates a new C<Class::MOP::Package> instance which
267represents specified package. If an existing metaclass object exists
57272677 268for the package, that will be returned instead. No options are valid at the
269package level.
38bf2a25 270
57272677 271=item B<< Class::MOP::Package->reinitialize($package, %options) >>
38bf2a25 272
273This method forcibly removes any existing metaclass for the package
274before calling C<initialize>. In contrast to C<initialize>, you may
275also pass an existing C<Class::MOP::Package> instance instead of just
276a package name as C<$package>.
277
278Do not call this unless you know what you are doing.
279
57272677 280=item B<< Class::MOP::Package->create($package, %options) >>
281
282Creates a new C<Class::MOP::Package> instance which represents the specified
283package, and also does some initialization of that package. Currently, this
284just does the same thing as C<initialize>, but is overridden in subclasses,
285such as C<Class::MOP::Class>.
286
287=item B<< Class::MOP::Package->create_anon(%options) >>
288
289Creates a new anonymous package. Valid keys for C<%options> are:
290
291=over 4
292
293=item C<weaken>
294
295If this is true (the default), the instance stored in C<Class::MOP>'s metaclass
296cache will be weakened, so that the anonymous package will be garbage collected
297when the returned instance goes out of scope.
298
299=back
300
301=item B<< $metapackage->is_anon >>
302
303Returns true if the package is an anonymous package.
304
38bf2a25 305=item B<< $metapackage->name >>
306
307This is returns the package's name, as passed to the constructor.
308
309=item B<< $metapackage->namespace >>
310
311This returns a hash reference to the package's symbol table. The keys
312are symbol names and the values are typeglob references.
313
314=item B<< $metapackage->add_package_symbol($variable_name, $initial_value) >>
315
316This method accepts a variable name and an optional initial value. The
317C<$variable_name> must contain a leading sigil.
318
319This method creates the variable in the package's symbol table, and
320sets it to the initial value if one was provided.
321
322=item B<< $metapackage->get_package_symbol($variable_name) >>
323
324Given a variable name, this method returns the variable as a reference
325or undef if it does not exist. The C<$variable_name> must contain a
326leading sigil.
327
328=item B<< $metapackage->get_or_add_package_symbol($variable_name) >>
329
330Given a variable name, this method returns the variable as a reference.
331If it does not exist, a default value will be generated if possible. The
332C<$variable_name> must contain a leading sigil.
333
334=item B<< $metapackage->has_package_symbol($variable_name) >>
335
336Returns true if there is a package variable defined for
337C<$variable_name>. The C<$variable_name> must contain a leading sigil.
338
339=item B<< $metapackage->remove_package_symbol($variable_name) >>
340
341This will remove the package variable specified C<$variable_name>. The
342C<$variable_name> must contain a leading sigil.
343
344=item B<< $metapackage->remove_package_glob($glob_name) >>
345
346Given the name of a glob, this will remove that glob from the
347package's symbol table. Glob names do not include a sigil. Removing
348the glob removes all variables and subroutines with the specified
349name.
350
351=item B<< $metapackage->list_all_package_symbols($type_filter) >>
352
353This will list all the glob names associated with the current
354package. These names do not have leading sigils.
355
356You can provide an optional type filter, which should be one of
357'SCALAR', 'ARRAY', 'HASH', or 'CODE'.
358
359=item B<< $metapackage->get_all_package_symbols($type_filter) >>
360
361This works much like C<list_all_package_symbols>, but it returns a
362hash reference. The keys are glob names and the values are references
363to the value for that name.
364
365=item B<< Class::MOP::Package->meta >>
366
367This will return a L<Class::MOP::Class> instance for this class.
368
369=back
370
371=cut