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