X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=lib%2FMouse%2FPurePerl.pm;h=72dcb368bfdb34271e145c4ecf22cdf5b49feccf;hp=8ff18ee7c427cae3405cd0f965181bf03002c309;hb=4c0fe06fa87e7c2c4ed1666e77ed52ae020f19d7;hpb=af04626de226ce78ec19d583e86fce4c1df2267d diff --git a/lib/Mouse/PurePerl.pm b/lib/Mouse/PurePerl.pm index 8ff18ee..72dcb36 100644 --- a/lib/Mouse/PurePerl.pm +++ b/lib/Mouse/PurePerl.pm @@ -18,15 +18,20 @@ sub is_class_loaded { return 0 if ref($class) || !defined($class) || !length($class); # walk the symbol table tree to avoid autovififying - # \*{${main::}{"Foo::"}} == \*main::Foo:: + # \*{${main::}{"Foo::"}{"Bar::"}} == \*main::Foo::Bar:: my $pack = \%::; foreach my $part (split('::', $class)) { - my $entry = \$pack->{$part . '::'}; + $part .= '::'; + return 0 if !exists $pack->{$part}; + + my $entry = \$pack->{$part}; return 0 if ref($entry) ne 'GLOB'; - $pack = *{$entry}{HASH} or return 0; + $pack = *{$entry}{HASH}; } + return 0 if !%{$pack}; + # check for $VERSION or @ISA return 1 if exists $pack->{VERSION} && defined *{$pack->{VERSION}}{SCALAR} && defined ${ $pack->{VERSION} }; @@ -199,11 +204,86 @@ sub add_method { return; } +my %SIGIL_MAP = ( + '$' => 'SCALAR', + '@' => 'ARRAY', + '%' => 'HASH', + '&' => 'CODE', + '*' => 'GLOB', +); + +sub _deconstruct_variable_name { + my($self, $variable) = @_; + + (defined $variable) + || $self->throw_error("You must pass a variable name"); + + my $sigil = substr($variable, 0, 1, ''); + + (defined $sigil) + || $self->throw_error("The variable name must include a sigil"); + + (exists $SIGIL_MAP{$sigil}) + || $self->throw_error("I do not recognize that sigil '$sigil'"); + + return ($variable, $SIGIL_MAP{$sigil}); +} + +sub has_package_symbol { + my($self, $variable) = @_; + + my($name, $type) = $self->_deconstruct_variable_name($variable); + + my $namespace = $self->namespace; + + return 0 unless exists $namespace->{$name}; + + my $entry_ref = \$namespace->{$name}; + if ( ref($entry_ref) eq 'GLOB' ) { + return defined( *{$entry_ref}{$type} ); + } + else { + # a symbol table entry can be -1 (stub), string (stub with prototype), + # or reference (constant) + return $type eq 'CODE'; + } +} + +sub get_package_symbol { + my ($self, $variable) = @_; + + my($name, $type) = $self->_deconstruct_variable_name($variable); + + my $namespace = $self->namespace; + + return undef + unless exists $namespace->{$name}; + + my $entry_ref = \$namespace->{$name}; + + if ( ref($entry_ref) eq 'GLOB' ) { + return *{$entry_ref}{$type}; + } + else { + if ( $type eq 'CODE' ) { + no strict 'refs'; + return \&{ $self->name . '::' . $name }; + } + else { + return undef; + } + } +} + package Mouse::Meta::Class; -sub constructor_class() { 'Mouse::Meta::Method::Constructor' } +sub method_metaclass { $_[0]->{method_metaclass} || 'Mouse::Meta::Method' } +sub attribute_metaclass { $_[0]->{attribute_metaclass} || 'Mouse::Meta::Attribute' } + +sub constructor_class { $_[0]->{constructor_class} || 'Mouse::Meta::Method::Constructor' } +sub destructor_class { $_[0]->{destructor_class} || 'Mouse::Meta::Method::Destructor' } sub is_anon_class{ return exists $_[0]->{anon_serial_id}; @@ -219,6 +299,16 @@ sub get_all_attributes { return values %attrs; } +sub new_object { + my $self = shift; + my %args = (@_ == 1 ? %{$_[0]} : @_); + + my $object = bless {}, $self->name; + + $self->_initialize_object($object, \%args); + return $object; +} + sub _initialize_object{ my($self, $object, $args, $ignore_triggers) = @_; @@ -277,6 +367,8 @@ sub _initialize_object{ package Mouse::Meta::Role; +sub method_metaclass{ $_[0]->{method_metaclass} || 'Mouse::Meta::Role::Method' } + sub is_anon_role{ return exists $_[0]->{anon_serial_id}; } @@ -286,7 +378,9 @@ sub get_roles { $_[0]->{roles} } package Mouse::Meta::Attribute; -use Mouse::Meta::Method::Accessor; +require Mouse::Meta::Method::Accessor; + +sub accessor_metaclass{ $_[0]->{accessor_metaclass} || 'Mouse::Meta::Method::Accessor' } # readers @@ -332,8 +426,6 @@ sub has_builder { exists $_[0]->{builder} } sub has_documentation { exists $_[0]->{documentation} } -sub accessor_metaclass(){ 'Mouse::Meta::Method::Accessor' } - package Mouse::Meta::TypeConstraint; @@ -435,6 +527,38 @@ sub new { return $self; } +sub DESTROY { + my $self = shift; + + return unless $self->can('DEMOLISH'); # short circuit + + local $?; + + my $e = do{ + local $@; + eval{ + + # DEMOLISHALL + + # We cannot count on being able to retrieve a previously made + # metaclass, _or_ being able to make a new one during global + # destruction. However, we should still be able to use mro at + # that time (at least tests suggest so ;) + + foreach my $class (@{ Mouse::Util::get_linear_isa(ref $self) }) { + my $demolish = Mouse::Util::get_code_ref($class, 'DEMOLISH') + || next; + + $self->$demolish(); + } + }; + $@; + }; + + no warnings 'misc'; + die $e if $e; # rethrow +} + 1; __END__ @@ -444,7 +568,7 @@ Mouse::PurePerl - A Mouse guts in pure Perl =head1 VERSION -This document describes Mouse version 0.40_05 +This document describes Mouse version 0.41 =head1 SEE ALSO