X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FClass%2FMOP%2FPackage.pm;h=2911d2e5f4bb9fdaee16130ab837756b0403e8e5;hb=c46b802b9f10829ddce24dbf3fb81d5319f8be8f;hp=184dd13c3eaa1319f088e02ee51924dbe44a0e33;hpb=a5e51f0baa6e418d27bf9f1514a5ac63fc879acb;p=gitmo%2FClass-MOP.git diff --git a/lib/Class/MOP/Package.pm b/lib/Class/MOP/Package.pm index 184dd13..2911d2e 100644 --- a/lib/Class/MOP/Package.pm +++ b/lib/Class/MOP/Package.pm @@ -69,22 +69,32 @@ sub namespace { $_[0]->{'%:namespace'} } # Class attributes +# ... these functions have to touch the symbol table itself,.. yuk + sub add_package_symbol { my ($self, $variable, $initial_value) = @_; my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); no strict 'refs'; - no warnings 'misc', 'redefine'; - *{$self->name . '::' . $name} = $initial_value; + no warnings 'redefine', 'misc'; + *{$self->name . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value; +} + +sub remove_package_glob { + my ($self, $name) = @_; + no strict 'refs'; + delete ${$self->name . '::'}{$name}; } +# ... these functions deal with stuff on the namespace level + sub has_package_symbol { my ($self, $variable) = @_; my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); - return 0 unless exists $self->namespace->{$name}; + return 0 unless exists $self->namespace->{$name}; defined *{$self->namespace->{$name}}{$type} ? 1 : 0; } @@ -93,9 +103,9 @@ sub get_package_symbol { my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); - return *{$self->namespace->{$name}}{$type} - if exists $self->namespace->{$name}; - $self->add_package_symbol($variable); + $self->add_package_symbol($variable) + unless exists $self->namespace->{$name}; + return *{$self->namespace->{$name}}{$type}; } sub remove_package_symbol { @@ -103,34 +113,41 @@ sub remove_package_symbol { my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); + # FIXME: + # no doubt this is grossly inefficient and + # could be done much easier and faster in XS + + my ($scalar, $array, $hash, $code); if ($type eq 'SCALAR') { - undef ${$self->namespace->{$name}}; + $array = $self->get_package_symbol('@' . $name) if $self->has_package_symbol('@' . $name); + $hash = $self->get_package_symbol('%' . $name) if $self->has_package_symbol('%' . $name); + $code = $self->get_package_symbol('&' . $name) if $self->has_package_symbol('&' . $name); } elsif ($type eq 'ARRAY') { - undef @{$self->namespace->{$name}}; + $scalar = $self->get_package_symbol('$' . $name) if $self->has_package_symbol('$' . $name); + $hash = $self->get_package_symbol('%' . $name) if $self->has_package_symbol('%' . $name); + $code = $self->get_package_symbol('&' . $name) if $self->has_package_symbol('&' . $name); } elsif ($type eq 'HASH') { - undef %{$self->namespace->{$name}}; + $scalar = $self->get_package_symbol('$' . $name) if $self->has_package_symbol('$' . $name); + $array = $self->get_package_symbol('@' . $name) if $self->has_package_symbol('@' . $name); + $code = $self->get_package_symbol('&' . $name) if $self->has_package_symbol('&' . $name); } elsif ($type eq 'CODE') { - # FIXME: - # this is crap, it is probably much - # easier to write this in XS. - my ($scalar, @array, %hash); - $scalar = ${$self->namespace->{$name}} if defined *{$self->namespace->{$name}}{SCALAR}; - @array = @{$self->namespace->{$name}} if defined *{$self->namespace->{$name}}{ARRAY}; - %hash = %{$self->namespace->{$name}} if defined *{$self->namespace->{$name}}{HASH}; - { - no strict 'refs'; - delete ${$self->name . '::'}{$name}; - } - ${$self->namespace->{$name}} = $scalar if defined $scalar; - @{$self->namespace->{$name}} = @array if scalar @array; - %{$self->namespace->{$name}} = %hash if keys %hash; + $scalar = $self->get_package_symbol('$' . $name) if $self->has_package_symbol('$' . $name); + $array = $self->get_package_symbol('@' . $name) if $self->has_package_symbol('@' . $name); + $hash = $self->get_package_symbol('%' . $name) if $self->has_package_symbol('%' . $name); } else { confess "This should never ever ever happen"; } + + $self->remove_package_glob($name); + + $self->add_package_symbol(('$' . $name) => $scalar) if defined $scalar; + $self->add_package_symbol(('@' . $name) => $array) if defined $array; + $self->add_package_symbol(('%' . $name) => $hash) if defined $hash; + $self->add_package_symbol(('&' . $name) => $code) if defined $code; } sub list_all_package_symbols { @@ -172,6 +189,8 @@ Class::MOP::Package - Package Meta Object =item B +=item B + =item B =back