no more XS mah!
[gitmo/Moose.git] / lib / Moose / Meta / Method / Destructor.pm
1
2 package Moose::Meta::Method::Destructor;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'blessed', 'weaken';
9
10 our $VERSION   = '0.03';
11 our $AUTHORITY = 'cpan:STEVAN';
12
13 use base 'Moose::Meta::Method',
14          'Class::MOP::Method::Generated';
15
16 sub new {
17     my $class   = shift;
18     my %options = @_;
19     
20     (exists $options{options} && ref $options{options} eq 'HASH')
21         || confess "You must pass a hash of options";    
22         
23     ($options{package_name} && $options{name})
24         || confess "You must supply the package_name and name parameters";        
25     
26     my $self = bless {
27         # from our superclass
28         '&!body'                 => undef, 
29         '$!package_name'         => $options{package_name},
30         '$!name'                 => $options{name},              
31         # ...
32         '%!options'              => $options{options},        
33         '$!associated_metaclass' => $options{metaclass},
34     } => $class;
35
36     # we don't want this creating 
37     # a cycle in the code, if not 
38     # needed
39     weaken($self->{'$!associated_metaclass'});    
40
41     $self->initialize_body;
42
43     return $self;    
44 }
45
46 ## accessors 
47
48 sub options              { (shift)->{'%!options'}              }
49 sub associated_metaclass { (shift)->{'$!associated_metaclass'} }
50
51 ## method
52
53 sub is_needed { defined $_[0]->{'&!body'} ? 1 : 0 }
54
55 sub initialize_body {
56     my $self = shift;
57     # TODO:
58     # the %options should also include a both 
59     # a call 'initializer' and call 'SUPER::' 
60     # options, which should cover approx 90% 
61     # of the possible use cases (even if it 
62     # requires some adaption on the part of 
63     # the author, after all, nothing is free)
64     my $source = 'sub {';
65
66     my @DEMOLISH_calls;
67     foreach my $method ($self->associated_metaclass->find_all_methods_by_name('DEMOLISH')) {
68         push @DEMOLISH_calls => '$_[0]->' . $method->{class} . '::DEMOLISH()';    
69     }
70     
71     $source .= join ";\n" => @DEMOLISH_calls;
72
73     $source .= ";\n" . '}'; 
74     warn $source if $self->options->{debug};    
75     
76     my $code;
77     {
78         $code = eval $source;
79         confess "Could not eval the destructor :\n\n$source\n\nbecause :\n\n$@" if $@;
80     }
81     $self->{'&!body'} = $code;
82 }
83
84
85 1;
86
87 __END__
88
89 =pod
90
91 =head1 NAME 
92
93 Moose::Meta::Method::Destructor - Method Meta Object for destructors
94
95 =head1 DESCRIPTION
96
97 This is a subclass of L<Class::MOP::Method> which handles 
98 constructing an approprate Destructor method. This is primarily 
99 used in the making of immutable metaclasses, otherwise it is 
100 not particularly useful.
101
102 =head1 METHODS
103
104 =over 4
105
106 =item B<new>
107
108 =item B<attributes>
109
110 =item B<meta_instance>
111
112 =item B<options>
113
114 =item B<is_needed>
115
116 =item B<initialize_body>
117
118 =item B<associated_metaclass>
119
120 =back
121
122 =head1 AUTHORS
123
124 Stevan Little E<lt>stevan@iinteractive.comE<gt>
125
126 =head1 COPYRIGHT AND LICENSE
127
128 Copyright 2006-2008 by Infinity Interactive, Inc.
129
130 L<http://www.iinteractive.com>
131
132 This library is free software; you can redistribute it and/or modify
133 it under the same terms as Perl itself. 
134
135 =cut
136