From: Stevan Little Date: Sat, 28 Oct 2006 18:17:57 +0000 (+0000) Subject: a few tweaks here and there and a new proposal for Immutable classes X-Git-Tag: 0_36~2^2~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a5ee59de83f8e67199604db8a57536ec2ced5894;p=gitmo%2FClass-MOP.git a few tweaks here and there and a new proposal for Immutable classes --- diff --git a/lib/Class/MOP/Class.pm b/lib/Class/MOP/Class.pm index 30760be..2467bbb 100644 --- a/lib/Class/MOP/Class.pm +++ b/lib/Class/MOP/Class.pm @@ -70,7 +70,6 @@ sub construct_class_instance { : blessed($class)) : $class); - $class = blessed($class) || $class; # now create the metaclass my $meta; if ($class =~ /^Class::MOP::Class$/) { diff --git a/lib/Class/MOP/Class/Immutable.pm b/lib/Class/MOP/Class/Immutable.pm index 2b020b4..0f58927 100644 --- a/lib/Class/MOP/Class/Immutable.pm +++ b/lib/Class/MOP/Class/Immutable.pm @@ -43,19 +43,6 @@ for my $meth (qw( }; } -sub get_package_symbol { - my ($self, $variable) = @_; - my ($name, $sigil, $type) = $self->_deconstruct_variable_name($variable); - return *{$self->namespace->{$name}}{$type} - if exists $self->namespace->{$name}; - # NOTE: - # we have to do this here in order to preserve - # perl's autovivification of variables. However - # we do cut off direct access to add_package_symbol - # as shown above. - $self->Class::MOP::Package::add_package_symbol($variable); -} - # NOTE: # superclasses is an accessor, so # it just cannot be changed @@ -109,7 +96,7 @@ sub make_metaclass_immutable { } # now cache the method map ... - $metaclass->{'___method_map'} = $metaclass->get_method_map; + $metaclass->{'___get_method_map'} = $metaclass->get_method_map; bless $metaclass => $class; } @@ -120,7 +107,7 @@ sub get_meta_instance { (shift)->{'___get_meta_instance'} sub class_precedence_list { @{(shift)->{'___class_precedence_list'}} } sub compute_all_applicable_attributes { @{(shift)->{'___compute_all_applicable_attributes'}} } sub get_mutable_metaclass_name { (shift)->{'___original_class'} } -sub get_method_map { (shift)->{'___method_map'} } +sub get_method_map { (shift)->{'___get_method_map'} } 1; @@ -241,11 +228,6 @@ to this method, which This method becomes read-only in an immutable class. -=item B - -This method must handle package variable autovivification -correctly, while still disallowing C. - =back =head2 Cached methods diff --git a/lib/Class/MOP/Immutable.pm b/lib/Class/MOP/Immutable.pm new file mode 100644 index 0000000..4e4c33e --- /dev/null +++ b/lib/Class/MOP/Immutable.pm @@ -0,0 +1,133 @@ + +package Class::MOP::Immutable; + +1; + +__END__ + +=pod + +Okay, so here is the basic idea. + +First, your metaclass must register with Class::MOP::Immutable +at which point an anon-class is created which will be the +immutable class which your metaclass will be blessed into. + +This allows immutable versions of any metaclass to be created +on the fly if needed. + +NOTE: +Remember the immutable version of the metaclass will be used to +construct/convert mutable instances into immutable versions. So +it itself is a metaclass. + + Class::MOP::Immutable->make_immutable_metaclass( + # name of the metaclass we are + # making immutable + metaclass => 'Class::MOP::Class', + + # names of some method metaclasses + # which will be useful in the creation + # of the immutable versions + constructor_class => 'Class::MOP::Method::Constructor', + accessor_class => 'Class::MOP::Method::Accessor', # ?? maybe + + # options which the immutable converter + # will accept, not exactly sure about + # this one,.. it might have to be hard + # coded in some way. + available_options => [qw[ + inline_accessors + inline_constructor + constructor_name + ]], + + # multiple lists of things which can + # be done to the metaclass .. + + # make these methods die when called + disallow => [qw[ + add_method + alias_method + remove_method + add_attribute + remove_attribute + add_package_symbol + remove_package_symbol + ]], + + # memoize the value of these methods + memoize => [qw[ + class_precedence_list + compute_all_applicable_attributes + get_meta_instance + get_method_map + ]], + + # make these methods read only + readonly => [qw[ + superclasses + ]], + ); + +Now, this will work just fine for singular metas, but +we want this to be able to work for extensions to the +metaclasses as well. + +Here is how we do that: + + Class::MOP::Immutable->make_immutable_metaclass( + # the metaclass name ... + metaclass => 'Moose::Meta::Class', + + # inherit the options from immutable + # parent class (Class::MOP::Class) + inherit => 1 + + constructor_class => 'Moose::Method::Constructor', + accessor_class => 'Moose::Method::Accessor', # ?? maybe + + disallow => [qw[ + add_roles + ... + ]], + + memoize => [qw[ + roles + ... + ]] + ); + +When you specify C 1> you are telling +Class::MOP::Immutable that you want to inherit your +parents options. This means that you get all their +and yours (perhaps some basic conflict resolution +can be added here as well). + +It might make sense to also allow a more granular +approach such as: + + inherit => { + disallow => 'merge', + memoize => 'override', + readonly => 'ignore', + } + +which would allow you to specify in more detail how +you would like to handle each change. This might be +more than anyone ever needs so we can probably hold +off for now. + +Ultimately it will be the responsibility of the +author to make sure their immutable options make sense. + +The reason I say this is that you could easily get +carried away in the number of items you choose to +memoize or such. This would not make a lot of sense, +it would make more sense to memoize at the "topmost" +level instead, rather than all the intermediate ones. + +It's basically gonna be a trade off. + +=cut + diff --git a/lib/Class/MOP/Method/Accessor.pm b/lib/Class/MOP/Method/Accessor.pm index 1f8eb04..237dd0e 100644 --- a/lib/Class/MOP/Method/Accessor.pm +++ b/lib/Class/MOP/Method/Accessor.pm @@ -232,8 +232,6 @@ Class::MOP::Method::Accessor - Method Meta Object for accessors Stevan Little Estevan@iinteractive.comE -Yuval Kogman Enothingmuch@woobling.comE - =head1 COPYRIGHT AND LICENSE Copyright 2006 by Infinity Interactive, Inc. diff --git a/lib/Class/MOP/Method/Constructor.pm b/lib/Class/MOP/Method/Constructor.pm index 7b7d921..08812bc 100644 --- a/lib/Class/MOP/Method/Constructor.pm +++ b/lib/Class/MOP/Method/Constructor.pm @@ -156,8 +156,6 @@ Class::MOP::Method::Constructor - Method Meta Object for constructors Stevan Little Estevan@iinteractive.comE -Yuval Kogman Enothingmuch@woobling.comE - =head1 COPYRIGHT AND LICENSE Copyright 2006 by Infinity Interactive, Inc.