X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FClass%2FMOP%2FInstance.pm;h=b2e406a8f4f60a1ff482e821d8892f91a47ae93b;hb=f0480c45f215203bc40abc794ac0c03622f02f1d;hp=7d1e573814d12e96b60e969d638365de77d6f4bb;hpb=24869f62f2c588b527cdb80aee59a9867e51f0ba;p=gitmo%2FClass-MOP.git diff --git a/lib/Class/MOP/Instance.pm b/lib/Class/MOP/Instance.pm index 7d1e573..b2e406a 100644 --- a/lib/Class/MOP/Instance.pm +++ b/lib/Class/MOP/Instance.pm @@ -4,10 +4,10 @@ package Class::MOP::Instance; use strict; use warnings; -use Carp 'confess'; -use Scalar::Util 'blessed', 'reftype', 'weaken'; +use Scalar::Util 'weaken', 'blessed'; -our $VERSION = '0.01'; +our $VERSION = '0.03'; +our $AUTHORITY = 'cpan:STEVAN'; sub meta { require Class::MOP::Class; @@ -15,19 +15,149 @@ sub meta { } sub new { - my $class = shift; - my $meta = shift; + my ($class, $meta, @attrs) = @_; + my @slots = map { $_->slots } @attrs; bless { - instance => bless {} => $meta->name + # NOTE: + # I am not sure that it makes + # sense to pass in the meta + # The ideal would be to just + # pass in the class name, but + # that is placing too much of + # an assumption on bless(), + # which is *probably* a safe + # assumption,.. but you can + # never tell <:) + meta => $meta, + slots => { map { $_ => undef } @slots }, } => $class; } -sub add_slot { - my ($self, $slot_name, $value) = @_; - return $self->{instance}->{$slot_name} = $value; +sub create_instance { + my $self = shift; + $self->bless_instance_structure({}); } -sub get_instance { (shift)->{instance} } +sub bless_instance_structure { + my ($self, $instance_structure) = @_; + bless $instance_structure, $self->{meta}->name; +} + +sub clone_instance { + my ($self, $instance) = @_; + $self->bless_instance_structure({ %$instance }); +} + +# operations on meta instance + +sub get_all_slots { + my $self = shift; + return keys %{$self->{slots}}; +} + +sub is_valid_slot { + my ($self, $slot_name) = @_; + exists $self->{slots}->{$slot_name} ? 1 : 0; +} + +# operations on created instances + +sub get_slot_value { + my ($self, $instance, $slot_name) = @_; + return $instance->{$slot_name}; +} + +sub set_slot_value { + my ($self, $instance, $slot_name, $value) = @_; + $instance->{$slot_name} = $value; +} + +sub initialize_slot { + my ($self, $instance, $slot_name) = @_; + $self->set_slot_value($instance, $slot_name, undef); +} + +sub deinitialize_slot { + my ( $self, $instance, $slot_name ) = @_; + delete $instance->{$slot_name}; +} + +sub initialize_all_slots { + my ($self, $instance) = @_; + foreach my $slot_name ($self->get_all_slots) { + $self->initialize_slot($instance, $slot_name); + } +} + +sub deinitialize_all_slots { + my ($self, $instance) = @_; + foreach my $slot_name ($self->get_all_slots) { + $self->deinitialize_slot($instance, $slot_name); + } +} + +sub is_slot_initialized { + my ($self, $instance, $slot_name, $value) = @_; + exists $instance->{$slot_name} ? 1 : 0; +} + +sub weaken_slot_value { + my ($self, $instance, $slot_name) = @_; + weaken $instance->{$slot_name}; +} + +sub strengthen_slot_value { + my ($self, $instance, $slot_name) = @_; + $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name)); +} + +# inlinable operation snippets + +sub is_inlinable { 1 } + +sub inline_create_instance { + my ($self, $class_variable) = @_; + 'bless {} => ' . $class_variable; +} + +sub inline_slot_access { + my ($self, $instance, $slot_name) = @_; + sprintf "%s->{%s}", $instance, $slot_name; +} + +sub inline_get_slot_value { + my ($self, $instance, $slot_name) = @_; + $self->inline_slot_access($instance, $slot_name); +} + +sub inline_set_slot_value { + my ($self, $instance, $slot_name, $value) = @_; + $self->inline_slot_access($instance, $slot_name) . " = $value", +} + +sub inline_initialize_slot { + my ($self, $instance, $slot_name) = @_; + $self->inline_set_slot_value($instance, $slot_name, 'undef'), +} + +sub inline_deinitialize_slot { + my ($self, $instance, $slot_name) = @_; + "delete " . $self->inline_slot_access($instance, $slot_name); +} +sub inline_is_slot_initialized { + my ($self, $instance, $slot_name) = @_; + "exists " . $self->inline_slot_access($instance, $slot_name) . " ? 1 : 0"; +} + +sub inline_weaken_slot_value { + my ($self, $instance, $slot_name) = @_; + sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name); +} + +sub inline_strengthen_slot_value { + my ($self, $instance, $slot_name) = @_; + $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name)); +} 1; @@ -41,32 +171,150 @@ Class::MOP::Instance - Instance Meta Object =head1 SYNOPSIS + # for the most part, this protocol is internal + # and not for public usage, but this how one + # might use it + + package Foo; + + use strict; + use warnings; + use metaclass ( + ':instance_metaclass' => 'ArrayBasedStorage::Instance', + ); + + # now Foo->new produces blessed ARRAY ref based objects + =head1 DESCRIPTION +This is a sub-protocol which governs instance creation +and access to the slots of the instance structure. + +This may seem like over-abstraction, but by abstracting +this process into a sub-protocol we make it possible to +easily switch the details of how an object's instance is +stored with minimal impact. In most cases just subclassing +this class will be all you need to do (see the examples; +F and +F for details). + =head1 METHODS =over 4 -=item B +=item B -=item B +Creates a new instance meta-object and gathers all the slots from +the list of C<@attrs> given. -=item B +=item B + +This will return a B instance which is related +to this class. =back -=head2 Introspection +=head2 Creation of Instances =over 4 -=item B +=item B -This will return a B instance which is related -to this class. +This creates the appropriate structure needed for the instance and +then calls C to bless it into the class. + +=item B + +This does just exactly what it says it does. + +=item B + +=back + +=head2 Instrospection + +NOTE: There might be more methods added to this part of the API, +we will add then when we need them basically. + +=over 4 + +=item B + +This will return the current list of slots based on what was +given to this object in C. + +=item B =back -=head1 AUTHOR +=head2 Operations on Instance Structures + +An important distinction of this sub-protocol is that the +instance meta-object is a different entity from the actual +instance it creates. For this reason, any actions on slots +require that the C<$instance_structure> is passed into them. + +=over 4 + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=back + +=head2 Inlineable Instance Operations + +This part of the API is currently un-used. It is there for use +in future experiments in class finailization mostly. Best to +ignore this for now. + +=over 4 + +=item B + +Each meta-instance should override this method to tell Class::MOP if it's +possible to inline the slot access. + +This is currently only used by Class::MOP::Class::Immutable when performing +optimizations. + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=back + +=head1 AUTHORS + +Yuval Kogman Enothingmuch@woobling.comE Stevan Little Estevan@iinteractive.comE @@ -79,4 +327,5 @@ 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 +