X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FClass%2FMOP%2FPackage.pm;h=3020727d0c6eb3754f6cde4956a74e5e502a1ba8;hb=9195ddff0447e2e618ab3b227aeb3574f6c8cb17;hp=2911d2e5f4bb9fdaee16130ab837756b0403e8e5;hpb=c46b802b9f10829ddce24dbf3fb81d5319f8be8f;p=gitmo%2FClass-MOP.git diff --git a/lib/Class/MOP/Package.pm b/lib/Class/MOP/Package.pm index 2911d2e..3020727 100644 --- a/lib/Class/MOP/Package.pm +++ b/lib/Class/MOP/Package.pm @@ -7,7 +7,10 @@ use warnings; use Scalar::Util 'blessed'; use Carp 'confess'; -our $VERSION = '0.02'; +our $VERSION = '0.07'; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Class::MOP::Object'; # introspection @@ -25,8 +28,15 @@ sub initialize { # until we can bootstrap it no strict 'refs'; return bless { - '$:package' => $package_name, - '%:namespace' => \%{$package_name . '::'}, + '$!package' => $package_name, + # NOTE: + # because of issues with the Perl API + # to the typeglob in some versions, we + # need to just always grab a new + # reference to the hash in the accessor. + # Ideally we could just store a ref and + # it would Just Work, but oh well :\ + '%!namespace' => \undef, } => $class; } @@ -36,8 +46,18 @@ sub initialize { # all these attribute readers will be bootstrapped # away in the Class::MOP bootstrap section -sub name { $_[0]->{'$:package'} } -sub namespace { $_[0]->{'%:namespace'} } +sub name { $_[0]->{'$!package'} } +sub namespace { + # NOTE: + # because of issues with the Perl API + # to the typeglob in some versions, we + # need to just always grab a new + # reference to the hash here. Ideally + # we could just store a ref and it would + # Just Work, but oh well :\ + no strict 'refs'; + \%{$_[0]->name . '::'} +} # utility methods @@ -77,8 +97,8 @@ sub add_package_symbol { my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); no strict 'refs'; - no warnings 'redefine', 'misc'; - *{$self->name . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value; + no warnings 'redefine', 'misc'; + *{$self->name . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value; } sub remove_package_glob { @@ -93,9 +113,28 @@ sub has_package_symbol { my ($self, $variable) = @_; my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); - + return 0 unless exists $self->namespace->{$name}; - defined *{$self->namespace->{$name}}{$type} ? 1 : 0; + + # FIXME: + # For some really stupid reason + # a typeglob will have a default + # value of \undef in the SCALAR + # slot, so we need to work around + # this. Which of course means that + # if you put \undef in your scalar + # then this is broken. + + if (ref($self->namespace->{$name}) eq 'SCALAR') { + return ($type eq 'CODE' ? 1 : 0); + } + elsif ($type eq 'SCALAR') { + my $val = *{$self->namespace->{$name}}{$type}; + return defined(${$val}) ? 1 : 0; + } + else { + defined(*{$self->namespace->{$name}}{$type}) ? 1 : 0; + } } sub get_package_symbol { @@ -105,7 +144,19 @@ sub get_package_symbol { $self->add_package_symbol($variable) unless exists $self->namespace->{$name}; - return *{$self->namespace->{$name}}{$type}; + + if (ref($self->namespace->{$name}) eq 'SCALAR') { + if ($type eq 'CODE') { + no strict 'refs'; + return \&{$self->name.'::'.$name}; + } + else { + return undef; + } + } + else { + return *{$self->namespace->{$name}}{$type}; + } } sub remove_package_symbol { @@ -151,8 +202,18 @@ sub remove_package_symbol { } sub list_all_package_symbols { - my ($self) = @_; - return keys %{$self->namespace}; + my ($self, $type_filter) = @_; + return keys %{$self->namespace} unless defined $type_filter; + # NOTE: + # or we can filter based on + # type (SCALAR|ARRAY|HASH|CODE) + my $namespace = $self->namespace; + return grep { + (ref($namespace->{$_}) + ? (ref($namespace->{$_}) eq 'SCALAR' && $type_filter eq 'CODE') + : (ref(\$namespace->{$_}) eq 'GLOB' + && defined(*{$namespace->{$_}}{$type_filter}))); + } keys %{$namespace}; } 1; @@ -175,23 +236,53 @@ Class::MOP::Package - Package Meta Object =item B -=item B +=item B =item B +This is a read-only attribute which returns the package name for the +given instance. + =item B -=item B +This returns a HASH reference to the symbol table. The keys of the +HASH are the symbol names, and the values are typeglob references. + +=item B + +Given a C<$variable_name>, which must contain a leading sigil, this +method will create that variable within the package which houses the +class. It also takes an optional C<$initial_value>, which must be a +reference of the same type as the sigil of the C<$variable_name> +implies. + +=item B -=item B +This will return a reference to the package variable in +C<$variable_name>. -=item B +=item B -=item B +Returns true (C<1>) if there is a package variable defined for +C<$variable_name>, and false (C<0>) otherwise. -=item B +=item B -=item B +This will attempt to remove the package variable at C<$variable_name>. + +=item B + +This will attempt to remove the entire typeglob associated with +C<$glob_name> from the package. + +=item B + +This will list all the glob names associated with the current package. +By inspecting the globs returned you can discern all the variables in +the package. + +By passing a C<$type_filter>, you can limit the list to only those +which match the filter (either SCALAR, ARRAY, HASH or CODE). =back @@ -199,15 +290,13 @@ Class::MOP::Package - Package Meta Object Stevan Little Estevan@iinteractive.comE -Yuval Kogman Enothingmuch@woobling.comE - =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Infinity Interactive, Inc. +Copyright 2006, 2007 by Infinity Interactive, Inc. L This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. -=cut \ No newline at end of file +=cut