line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mouse::Meta::Method::Accessor; |
2
|
1
|
|
|
1
|
|
3
|
use Mouse::Util qw(:meta); # enables strict and warnings |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
3
|
|
|
|
|
|
|
|
4
|
1
|
50
|
|
1
|
|
4
|
use constant _MOUSE_DEBUG => $ENV{MOUSE_DEBUG} ? 1 : 0; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
826
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
sub _inline_slot{ |
7
|
0
|
|
|
0
|
|
|
my(undef, $self_var, $attr_name) = @_; |
8
|
0
|
|
|
|
|
|
return sprintf '%s->{q{%s}}', $self_var, $attr_name; |
9
|
|
|
|
|
|
|
} |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub _generate_accessor_any{ |
12
|
0
|
|
|
0
|
|
|
my($method_class, $type, $attribute, $class) = @_; |
13
|
|
|
|
|
|
|
|
14
|
0
|
|
|
|
|
|
my $name = $attribute->name; |
15
|
0
|
|
|
|
|
|
my $default = $attribute->default; |
16
|
0
|
|
|
|
|
|
my $constraint = $attribute->type_constraint; |
17
|
0
|
|
|
|
|
|
my $builder = $attribute->builder; |
18
|
0
|
|
|
|
|
|
my $trigger = $attribute->trigger; |
19
|
0
|
|
|
|
|
|
my $is_weak = $attribute->is_weak_ref; |
20
|
0
|
|
|
|
|
|
my $should_deref = $attribute->should_auto_deref; |
21
|
0
|
|
0
|
|
|
|
my $should_coerce = (defined($constraint) |
22
|
|
|
|
|
|
|
&& $constraint->has_coercion |
23
|
|
|
|
|
|
|
&& $attribute->should_coerce); |
24
|
|
|
|
|
|
|
|
25
|
0
|
0
|
|
|
|
|
my $compiled_type_constraint = defined($constraint) |
26
|
|
|
|
|
|
|
? $constraint->_compiled_type_constraint |
27
|
|
|
|
|
|
|
: undef; |
28
|
|
|
|
|
|
|
|
29
|
0
|
|
|
|
|
|
my $self = '$_[0]'; |
30
|
0
|
|
|
|
|
|
my $slot = $method_class->_inline_slot($self, $name);; |
31
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
my $accessor = sprintf(qq{package %s;\n#line 1 "%s-accessor for %s (%s)"\n}, $class->name, $type, $name, __FILE__) |
33
|
|
|
|
|
|
|
. "sub {\n"; |
34
|
|
|
|
|
|
|
|
35
|
0
|
0
|
0
|
|
|
|
if ($type eq 'rw' || $type eq 'wo') { |
|
|
0
|
|
|
|
|
|
36
|
0
|
0
|
|
|
|
|
if($type eq 'rw'){ |
37
|
0
|
|
|
|
|
|
$accessor .= |
38
|
|
|
|
|
|
|
'if (scalar(@_) >= 2) {' . "\n"; |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
else{ # writer |
41
|
0
|
|
|
|
|
|
$accessor .= |
42
|
|
|
|
|
|
|
'if(@_ < 2){ Carp::confess("Not enough arguments for the writer of $name") }'. |
43
|
|
|
|
|
|
|
'{' . "\n"; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
|
my $value = '$_[1]'; |
47
|
|
|
|
|
|
|
|
48
|
0
|
0
|
|
|
|
|
if (defined $constraint) { |
49
|
0
|
0
|
|
|
|
|
if ($should_coerce) { |
50
|
0
|
|
|
|
|
|
$accessor .= |
51
|
|
|
|
|
|
|
"\n". |
52
|
|
|
|
|
|
|
'my $val = $constraint->coerce('.$value.');'; |
53
|
0
|
|
|
|
|
|
$value = '$val'; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
$accessor .= |
56
|
0
|
|
|
|
|
|
"\n". |
57
|
|
|
|
|
|
|
'$compiled_type_constraint->('.$value.') or |
58
|
|
|
|
|
|
|
$attribute->_throw_type_constraint_error('.$value.', $constraint);' . "\n"; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# if there's nothing left to do for the attribute we can return during |
62
|
|
|
|
|
|
|
# this setter |
63
|
0
|
0
|
0
|
|
|
|
$accessor .= 'return ' if !$is_weak && !$trigger && !$should_deref; |
|
|
|
0
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
|
$accessor .= "my \@old_value = exists $slot ? $slot : ();\n" if $trigger; |
66
|
0
|
|
|
|
|
|
$accessor .= "$slot = $value;\n"; |
67
|
|
|
|
|
|
|
|
68
|
0
|
0
|
|
|
|
|
if ($is_weak) { |
69
|
0
|
|
|
|
|
|
$accessor .= "Scalar::Util::weaken($slot) if ref $slot;\n"; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
0
|
0
|
|
|
|
|
if ($trigger) { |
73
|
0
|
|
|
|
|
|
$accessor .= '$trigger->('.$self.', '.$value.', @old_value);' . "\n"; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
0
|
|
|
|
|
|
$accessor .= "}\n"; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
elsif($type eq 'ro') { |
79
|
0
|
|
|
|
|
|
$accessor .= 'Carp::confess("Cannot assign a value to a read-only accessor of $name") if scalar(@_) >= 2;' . "\n"; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
else{ |
82
|
0
|
|
|
|
|
|
$class->throw_error("Unknown accessor type '$type'"); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
0
|
0
|
0
|
|
|
|
if ($attribute->is_lazy and $type ne 'wo') { |
86
|
0
|
|
|
|
|
|
my $value; |
87
|
|
|
|
|
|
|
|
88
|
0
|
0
|
|
|
|
|
if (defined $builder){ |
|
|
0
|
|
|
|
|
|
89
|
0
|
|
|
|
|
|
$value = "$self->\$builder()"; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
elsif (ref($default) eq 'CODE'){ |
92
|
0
|
|
|
|
|
|
$value = "$self->\$default()"; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
else{ |
95
|
0
|
|
|
|
|
|
$value = '$default'; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
0
|
0
|
|
|
|
|
$accessor .= "els" if $type eq 'rw'; |
99
|
0
|
|
|
|
|
|
$accessor .= "if(!exists $slot){\n"; |
100
|
0
|
0
|
|
|
|
|
if($should_coerce){ |
|
|
0
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
$accessor .= "$slot = \$constraint->coerce($value)"; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
elsif(defined $constraint){ |
104
|
0
|
|
|
|
|
|
$accessor .= "my \$tmp = $value;\n"; |
105
|
0
|
|
|
|
|
|
$accessor .= "\$compiled_type_constraint->(\$tmp)"; |
106
|
0
|
|
|
|
|
|
$accessor .= " || \$attribute->_throw_type_constraint_error(\$tmp, \$constraint);\n"; |
107
|
0
|
|
|
|
|
|
$accessor .= "$slot = \$tmp;\n"; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
else{ |
110
|
0
|
|
|
|
|
|
$accessor .= "$slot = $value;\n"; |
111
|
|
|
|
|
|
|
} |
112
|
0
|
0
|
|
|
|
|
if ($is_weak) { |
113
|
0
|
|
|
|
|
|
$accessor .= "Scalar::Util::weaken($slot) if ref $slot;\n"; |
114
|
|
|
|
|
|
|
} |
115
|
0
|
|
|
|
|
|
$accessor .= "}\n"; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
0
|
0
|
|
|
|
|
if ($should_deref) { |
119
|
0
|
0
|
|
|
|
|
if ($constraint->is_a_type_of('ArrayRef')) { |
|
|
0
|
|
|
|
|
|
120
|
0
|
|
|
|
|
|
$accessor .= "return \@{ $slot || [] } if wantarray;\n"; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
elsif($constraint->is_a_type_of('HashRef')){ |
123
|
0
|
|
|
|
|
|
$accessor .= "return \%{ $slot || {} } if wantarray;\n"; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
else{ |
126
|
0
|
|
|
|
|
|
$class->throw_error("Can not auto de-reference the type constraint " . $constraint->name); |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
$accessor .= "return $slot;\n}\n"; |
131
|
|
|
|
|
|
|
|
132
|
0
|
|
|
|
|
|
warn $accessor if _MOUSE_DEBUG; |
133
|
0
|
|
|
|
|
|
my $code; |
134
|
0
|
|
|
|
|
|
my $e = do{ |
135
|
0
|
|
|
|
|
|
local $@; |
136
|
0
|
|
|
|
|
|
$code = eval $accessor; |
137
|
0
|
|
|
|
|
|
$@; |
138
|
|
|
|
|
|
|
}; |
139
|
0
|
0
|
|
|
|
|
die $e if $e; |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
return $code; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub _generate_accessor{ |
145
|
|
|
|
|
|
|
#my($self, $attribute, $metaclass) = @_; |
146
|
0
|
|
|
0
|
|
|
my $self = shift; |
147
|
0
|
|
|
|
|
|
return $self->_generate_accessor_any(rw => @_); |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub _generate_reader { |
151
|
|
|
|
|
|
|
#my($self, $attribute, $metaclass) = @_; |
152
|
0
|
|
|
0
|
|
|
my $self = shift; |
153
|
0
|
|
|
|
|
|
return $self->_generate_accessor_any(ro => @_); |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub _generate_writer { |
157
|
|
|
|
|
|
|
#my($self, $attribute, $metaclass) = @_; |
158
|
0
|
|
|
0
|
|
|
my $self = shift; |
159
|
0
|
|
|
|
|
|
return $self->_generate_accessor_any(wo => @_); |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub _generate_predicate { |
163
|
|
|
|
|
|
|
#my($self, $attribute, $metaclass) = @_; |
164
|
0
|
|
|
0
|
|
|
my(undef, $attribute) = @_; |
165
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
my $slot = $attribute->name; |
167
|
|
|
|
|
|
|
return sub{ |
168
|
0
|
|
|
0
|
|
|
return exists $_[0]->{$slot}; |
169
|
0
|
|
|
|
|
|
}; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub _generate_clearer { |
173
|
|
|
|
|
|
|
#my($self, $attribute, $metaclass) = @_; |
174
|
0
|
|
|
0
|
|
|
my(undef, $attribute) = @_; |
175
|
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
my $slot = $attribute->name; |
177
|
|
|
|
|
|
|
return sub{ |
178
|
0
|
|
|
0
|
|
|
delete $_[0]->{$slot}; |
179
|
0
|
|
|
|
|
|
}; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
1; |
183
|
|
|
|
|
|
|
__END__ |