use Scalar::Util 'blessed';
use Carp 'confess';
-our $VERSION = '0.05';
+our $VERSION = '0.09';
our $AUTHORITY = 'cpan:STEVAN';
use base 'Class::MOP::Object';
-# introspection
-
-sub meta {
- require Class::MOP::Class;
- Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
-}
-
# creation ...
sub initialize {
# all these attribute readers will be bootstrapped
# away in the Class::MOP bootstrap section
-sub name { $_[0]->{'$!package'} }
+sub name { $_[0]->{'$!package'} }
sub namespace {
# NOTE:
# because of issues with the Perl API
# we could just store a ref and it would
# Just Work, but oh well :\
no strict 'refs';
- \%{$_[0]->name . '::'}
+ \%{$_[0]->{'$!package'} . '::'}
}
# utility methods
(defined $variable)
|| confess "You must pass a variable name";
- my ($sigil, $name) = ($variable =~ /^(.)(.*)$/);
+ my $sigil = substr($variable, 0, 1, '');
(defined $sigil)
|| confess "The variable name must include a sigil";
(exists $SIGIL_MAP{$sigil})
|| confess "I do not recognize that sigil '$sigil'";
- return ($name, $sigil, $SIGIL_MAP{$sigil});
+ return ($variable, $sigil, $SIGIL_MAP{$sigil});
}
}
my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
+ my $pkg = $self->{'$!package'};
+
no strict 'refs';
no warnings 'redefine', 'misc';
- *{$self->name . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value;
+ *{$pkg . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value;
}
sub remove_package_glob {
my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
- return 0 unless exists $self->namespace->{$name};
+ my $namespace = $self->namespace;
+
+ return 0 unless exists $namespace->{$name};
# FIXME:
# For some really stupid reason
# this. Which of course means that
# if you put \undef in your scalar
# then this is broken.
-
- if ($type eq 'SCALAR') {
- my $val = *{$self->namespace->{$name}}{$type};
- defined(${$val}) ? 1 : 0;
+
+ if (ref($namespace->{$name}) eq 'SCALAR') {
+ return ($type eq 'CODE' ? 1 : 0);
+ }
+ elsif ($type eq 'SCALAR') {
+ my $val = *{$namespace->{$name}}{$type};
+ return defined(${$val}) ? 1 : 0;
}
else {
- defined(*{$self->namespace->{$name}}{$type}) ? 1 : 0;
+ defined(*{$namespace->{$name}}{$type}) ? 1 : 0;
}
}
my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable);
+ my $namespace = $self->namespace;
+
$self->add_package_symbol($variable)
- unless exists $self->namespace->{$name};
- return *{$self->namespace->{$name}}{$type};
+ unless exists $namespace->{$name};
+
+ if (ref($namespace->{$name}) eq 'SCALAR') {
+ if ($type eq 'CODE') {
+ no strict 'refs';
+ return \&{$self->name.'::'.$name};
+ }
+ else {
+ return undef;
+ }
+ }
+ else {
+ return *{$namespace->{$name}}{$type};
+ }
}
sub remove_package_symbol {
sub list_all_package_symbols {
my ($self, $type_filter) = @_;
- return keys %{$self->namespace} unless defined $type_filter;
+
+ my $namespace = $self->namespace;
+ return keys %{$namespace} unless defined $type_filter;
+
# NOTE:
# or we can filter based on
# type (SCALAR|ARRAY|HASH|CODE)
- my $namespace = $self->namespace;
return grep {
- defined(*{$namespace->{$_}}{$type_filter})
+ (ref($namespace->{$_})
+ ? (ref($namespace->{$_}) eq 'SCALAR' && $type_filter eq 'CODE')
+ : (ref(\$namespace->{$_}) eq 'GLOB'
+ && defined(*{$namespace->{$_}}{$type_filter})));
+ } keys %{$namespace};
+}
+
+sub get_all_package_symbols {
+ my ($self, $type_filter) = @_;
+ my $namespace = $self->namespace;
+ return %{$namespace} unless defined $type_filter;
+
+ # NOTE:
+ # or we can filter based on
+ # type (SCALAR|ARRAY|HASH|CODE)
+ no strict 'refs';
+ return map {
+ $_ => (ref($namespace->{$_}) eq 'SCALAR'
+ ? ($type_filter eq 'CODE' ? \&{$self->name . '::' . $_} : undef)
+ : *{$namespace->{$_}}{$type_filter})
+ } grep {
+ (ref($namespace->{$_})
+ ? (ref($namespace->{$_}) eq 'SCALAR' && $type_filter eq 'CODE')
+ : (ref(\$namespace->{$_}) eq 'GLOB'
+ && defined(*{$namespace->{$_}}{$type_filter})));
} keys %{$namespace};
}
Class::MOP::Package - Package Meta Object
-=head1 SYNOPSIS
-
=head1 DESCRIPTION
+This is an abstraction of a Perl 5 package, it is a superclass of
+L<Class::MOP::Class> and provides all of the symbol table
+introspection methods.
+
=head1 METHODS
=over 4
=item B<meta>
+Returns a metaclass for this package.
+
=item B<initialize ($package_name)>
+This will initialize a Class::MOP::Package instance which represents
+the package of C<$package_name>.
+
=item B<name>
This is a read-only attribute which returns the package name for the
By passing a C<$type_filter>, you can limit the list to only those
which match the filter (either SCALAR, ARRAY, HASH or CODE).
+=item B<get_all_package_symbols (?$type_filter)>
+
+Works exactly like C<list_all_package_symbols> but returns a HASH of
+name => thing mapping instead of just an ARRAY of names.
+
=back
=head1 AUTHORS
Stevan Little E<lt>stevan@iinteractive.comE<gt>
-Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
-
=head1 COPYRIGHT AND LICENSE
-Copyright 2006 by Infinity Interactive, Inc.
+Copyright 2006-2008 by Infinity Interactive, Inc.
L<http://www.iinteractive.com>
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