Beginning of dzilization
[gitmo/Moose.git] / lib / Moose / Meta / Method / Accessor / Native.pm
1 package Moose::Meta::Method::Accessor::Native;
2
3 use strict;
4 use warnings;
5
6 use Carp qw( confess );
7 use Scalar::Util qw( blessed weaken );
8
9 our $AUTHORITY = 'cpan:STEVAN';
10
11 use Moose::Role;
12
13 around new => sub {
14     my $orig = shift;
15     my $class   = shift;
16     my %options = @_;
17
18     $options{curried_arguments} = []
19         unless exists $options{curried_arguments};
20
21     confess 'You must supply a curried_arguments which is an ARRAY reference'
22         unless $options{curried_arguments}
23             && ref($options{curried_arguments}) eq 'ARRAY';
24
25     $options{definition_context} = $options{attribute}->definition_context;
26
27     $options{accessor_type} = 'native';
28
29     return $class->$orig(%options);
30 };
31
32 sub _new {
33     my $class = shift;
34     my $options = @_ == 1 ? $_[0] : {@_};
35
36     return bless $options, $class;
37 }
38
39 sub root_types { (shift)->{'root_types'} }
40
41 sub _initialize_body {
42     my $self = shift;
43
44     $self->{'body'} = $self->_compile_code( [$self->_generate_method] );
45
46     return;
47 }
48
49 sub _inline_curried_arguments {
50     my $self = shift;
51
52     return unless @{ $self->curried_arguments };
53
54     return 'unshift @_, @curried;';
55 }
56
57 sub _inline_check_argument_count {
58     my $self = shift;
59
60     my @code;
61
62     if (my $min = $self->_minimum_arguments) {
63         push @code, (
64             'if (@_ < ' . $min . ') {',
65                 $self->_inline_throw_error(
66                     sprintf(
67                         '"Cannot call %s without at least %s argument%s"',
68                         $self->delegate_to_method,
69                         $min,
70                         ($min == 1 ? '' : 's'),
71                     )
72                 ) . ';',
73             '}',
74         );
75     }
76
77     if (defined(my $max = $self->_maximum_arguments)) {
78         push @code, (
79             'if (@_ > ' . $max . ') {',
80                 $self->_inline_throw_error(
81                     sprintf(
82                         '"Cannot call %s with %s argument%s"',
83                         $self->delegate_to_method,
84                         $max ? "more than $max" : 'any',
85                         ($max == 1 ? '' : 's'),
86                     )
87                 ) . ';',
88             '}',
89         );
90     }
91
92     return @code;
93 }
94
95 sub _inline_return_value {
96     my $self = shift;
97     my ($slot_access, $for_writer) = @_;
98
99     return 'return ' . $self->_return_value($slot_access, $for_writer) . ';';
100 }
101
102 sub _minimum_arguments { 0 }
103 sub _maximum_arguments { undef }
104
105 override _get_value => sub {
106     my $self = shift;
107     my ($instance) = @_;
108
109     return $self->_slot_access_can_be_inlined
110         ? super()
111         : $instance . '->$reader';
112 };
113
114 override _inline_store_value => sub {
115     my $self = shift;
116     my ($instance, $value) = @_;
117
118     return $self->_slot_access_can_be_inlined
119         ? super()
120         : $instance . '->$writer(' . $value . ');';
121 };
122
123 override _eval_environment => sub {
124     my $self = shift;
125
126     my $env = super();
127
128     $env->{'@curried'} = $self->curried_arguments;
129
130     return $env if $self->_slot_access_can_be_inlined;
131
132     my $reader = $self->associated_attribute->get_read_method_ref;
133     $reader = $reader->body if blessed $reader;
134
135     $env->{'$reader'} = \$reader;
136
137     my $writer = $self->associated_attribute->get_write_method_ref;
138     $writer = $writer->body if blessed $writer;
139
140     $env->{'$writer'} = \$writer;
141
142     return $env;
143 };
144
145 sub _slot_access_can_be_inlined {
146     my $self = shift;
147
148     return $self->is_inline && $self->_instance_is_inlinable;
149 }
150
151 no Moose::Role;
152
153 1;