no ref in the defaults
[gitmo/Class-MOP.git] / lib / Class / MOP / Package.pm
CommitLineData
2243a22b 1
2package Class::MOP::Package;
3
4use strict;
5use warnings;
6
7use Scalar::Util 'blessed';
6d5355c3 8use Carp 'confess';
2243a22b 9
f0480c45 10our $VERSION = '0.02';
11our $AUTHORITY = 'cpan:STEVAN';
2243a22b 12
6e57504d 13use base 'Class::MOP::Object';
14
2243a22b 15# introspection
16
17sub meta {
18 require Class::MOP::Class;
19 Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
20}
21
6d5355c3 22# creation ...
23
24sub initialize {
9d6dce77 25 my $class = shift;
26 my $package_name = shift;
27 # we hand-construct the class
28 # until we can bootstrap it
a5e51f0b 29 no strict 'refs';
30 return bless {
31 '$:package' => $package_name,
32 '%:namespace' => \%{$package_name . '::'},
33 } => $class;
6d5355c3 34}
35
36# Attributes
37
38# NOTE:
39# all these attribute readers will be bootstrapped
40# away in the Class::MOP bootstrap section
41
a5e51f0b 42sub name { $_[0]->{'$:package'} }
43sub namespace { $_[0]->{'%:namespace'} }
6d5355c3 44
a5e51f0b 45# utility methods
6d5355c3 46
c0cbf4d9 47{
48 my %SIGIL_MAP = (
49 '$' => 'SCALAR',
50 '@' => 'ARRAY',
51 '%' => 'HASH',
52 '&' => 'CODE',
53 );
6d5355c3 54
a5e51f0b 55 sub _deconstruct_variable_name {
56 my ($self, $variable) = @_;
57
c0cbf4d9 58 (defined $variable)
59 || confess "You must pass a variable name";
a5e51f0b 60
c0cbf4d9 61 my ($sigil, $name) = ($variable =~ /^(.)(.*)$/);
a5e51f0b 62
c0cbf4d9 63 (defined $sigil)
64 || confess "The variable name must include a sigil";
a5e51f0b 65
c0cbf4d9 66 (exists $SIGIL_MAP{$sigil})
a5e51f0b 67 || confess "I do not recognize that sigil '$sigil'";
68
69 return ($name, $sigil, $SIGIL_MAP{$sigil});
c0cbf4d9 70 }
a5e51f0b 71}
6d5355c3 72
a5e51f0b 73# Class attributes
6d5355c3 74
c46b802b 75# ... these functions have to touch the symbol table itself,.. yuk
76
a5e51f0b 77sub add_package_symbol {
78 my ($self, $variable, $initial_value) = @_;
6d5355c3 79
a5e51f0b 80 my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
6d5355c3 81
a5e51f0b 82 no strict 'refs';
c20522bd 83 no warnings 'redefine', 'misc';
c46b802b 84 *{$self->name . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value;
85}
86
87sub remove_package_glob {
88 my ($self, $name) = @_;
89 no strict 'refs';
90 delete ${$self->name . '::'}{$name};
a5e51f0b 91}
6d5355c3 92
c46b802b 93# ... these functions deal with stuff on the namespace level
94
a5e51f0b 95sub has_package_symbol {
96 my ($self, $variable) = @_;
97
98 my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
99
c20522bd 100 return 0 unless exists $self->namespace->{$name};
d852f4d2 101
102 # FIXME:
103 # For some really stupid reason
104 # a typeglob will have a default
105 # value of \undef in the SCALAR
106 # slot, so we need to work around
107 # this. Which of course means that
108 # if you put \undef in your scalar
109 # then this is broken.
110
111 if ($type eq 'SCALAR') {
112 my $val = *{$self->namespace->{$name}}{$type};
113 defined $$val ? 1 : 0;
114 }
115 else {
116 defined *{$self->namespace->{$name}}{$type} ? 1 : 0;
117 }
a5e51f0b 118}
119
120sub get_package_symbol {
121 my ($self, $variable) = @_;
122
123 my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
124
c20522bd 125 $self->add_package_symbol($variable)
126 unless exists $self->namespace->{$name};
127 return *{$self->namespace->{$name}}{$type};
a5e51f0b 128}
129
130sub remove_package_symbol {
131 my ($self, $variable) = @_;
132
133 my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
134
c46b802b 135 # FIXME:
136 # no doubt this is grossly inefficient and
137 # could be done much easier and faster in XS
138
139 my ($scalar, $array, $hash, $code);
a5e51f0b 140 if ($type eq 'SCALAR') {
c46b802b 141 $array = $self->get_package_symbol('@' . $name) if $self->has_package_symbol('@' . $name);
142 $hash = $self->get_package_symbol('%' . $name) if $self->has_package_symbol('%' . $name);
143 $code = $self->get_package_symbol('&' . $name) if $self->has_package_symbol('&' . $name);
a5e51f0b 144 }
145 elsif ($type eq 'ARRAY') {
c46b802b 146 $scalar = $self->get_package_symbol('$' . $name) if $self->has_package_symbol('$' . $name);
147 $hash = $self->get_package_symbol('%' . $name) if $self->has_package_symbol('%' . $name);
148 $code = $self->get_package_symbol('&' . $name) if $self->has_package_symbol('&' . $name);
a5e51f0b 149 }
150 elsif ($type eq 'HASH') {
c46b802b 151 $scalar = $self->get_package_symbol('$' . $name) if $self->has_package_symbol('$' . $name);
152 $array = $self->get_package_symbol('@' . $name) if $self->has_package_symbol('@' . $name);
153 $code = $self->get_package_symbol('&' . $name) if $self->has_package_symbol('&' . $name);
a5e51f0b 154 }
155 elsif ($type eq 'CODE') {
c46b802b 156 $scalar = $self->get_package_symbol('$' . $name) if $self->has_package_symbol('$' . $name);
157 $array = $self->get_package_symbol('@' . $name) if $self->has_package_symbol('@' . $name);
158 $hash = $self->get_package_symbol('%' . $name) if $self->has_package_symbol('%' . $name);
a5e51f0b 159 }
160 else {
161 confess "This should never ever ever happen";
7f436b8c 162 }
c46b802b 163
164 $self->remove_package_glob($name);
165
166 $self->add_package_symbol(('$' . $name) => $scalar) if defined $scalar;
167 $self->add_package_symbol(('@' . $name) => $array) if defined $array;
168 $self->add_package_symbol(('%' . $name) => $hash) if defined $hash;
169 $self->add_package_symbol(('&' . $name) => $code) if defined $code;
9d6dce77 170}
c0cbf4d9 171
9d6dce77 172sub list_all_package_symbols {
173 my ($self) = @_;
a5e51f0b 174 return keys %{$self->namespace};
6d5355c3 175}
176
2243a22b 1771;
178
179__END__
180
181=pod
182
183=head1 NAME
184
185Class::MOP::Package - Package Meta Object
186
187=head1 SYNOPSIS
188
189=head1 DESCRIPTION
190
191=head1 METHODS
192
193=over 4
194
195=item B<meta>
196
6d5355c3 197=item B<initialize>
198
199=item B<name>
200
a5e51f0b 201=item B<namespace>
202
58d75218 203=item B<add_package_symbol>
6d5355c3 204
58d75218 205=item B<get_package_symbol>
6d5355c3 206
58d75218 207=item B<has_package_symbol>
6d5355c3 208
58d75218 209=item B<remove_package_symbol>
6d5355c3 210
c46b802b 211=item B<remove_package_glob>
212
9d6dce77 213=item B<list_all_package_symbols>
214
2243a22b 215=back
216
1a09d9cc 217=head1 AUTHORS
2243a22b 218
219Stevan Little E<lt>stevan@iinteractive.comE<gt>
220
1a09d9cc 221Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
222
2243a22b 223=head1 COPYRIGHT AND LICENSE
224
225Copyright 2006 by Infinity Interactive, Inc.
226
227L<http://www.iinteractive.com>
228
229This library is free software; you can redistribute it and/or modify
230it under the same terms as Perl itself.
231
232=cut