sub has_eager_default {
my ($self, $name, $spec) = @_;
- (!$spec->{lazy} and ($spec->{default} or $spec->{builder}));
+ (!$spec->{lazy} and (exists $spec->{default} or $spec->{builder}));
}
sub _generate_get {
." ".$self->_generate_isa_check($name, '$value', $spec->{isa}).";\n"
." ".$self->_generate_simple_set($me, $name, $spec, '$value')."\n"
." }\n"
- : ' '.$self->_generate_simple_set($me, $name, $spec, $get_value)."\n");
+ : ' ('.$self->_generate_simple_set($me, $name, $spec, $get_value).")\n");
}
sub _generate_get_default {
$self->_generate_simple_set('$_[0]', $name, $spec, '$_[1]');
} else {
my ($coerce, $trigger, $isa_check) = @{$spec}{qw(coerce trigger isa)};
- my $simple = $self->_generate_simple_set('$self', $name, $spec, '$value');
- my $code = "do { my (\$self, \$value) = \@_;\n";
+ my $value_store = '$_[0]';
+ my $code;
if ($coerce) {
- $code .=
- " \$value = "
- .$self->_generate_coerce($name, '$value', $coerce).";\n";
+ $value_store = '$value';
+ $code = "do { my (\$self, \$value) = \@_;\n"
+ ." \$value = "
+ .$self->_generate_coerce($name, $value_store, $coerce).";\n";
+ }
+ else {
+ $code = "do { my \$self = shift;\n";
}
if ($isa_check) {
$code .=
- " ".$self->_generate_isa_check($name, '$value', $isa_check).";\n";
+ " ".$self->_generate_isa_check($name, $value_store, $isa_check).";\n";
}
+ my $simple = $self->_generate_simple_set('$self', $name, $spec, $value_store);
if ($trigger) {
- my $fire = $self->_generate_trigger($name, '$self', '$value', $trigger);
+ my $fire = $self->_generate_trigger($name, '$self', $value_store, $trigger);
$code .=
" ".$simple.";\n ".$fire.";\n"
- ." \$value;\n";
+ ." $value_store;\n";
} else {
$code .= " ".$simple.";\n";
}
sub _generate_coerce {
my ($self, $name, $value, $coerce, $init_arg) = @_;
$self->_generate_die_prefix(
- "coercion for ${\_attr_desc($name, $init_arg)} failed: ",
+ $name,
+ "coercion",
+ $init_arg,
$self->_generate_call_code($name, 'coerce', "${value}", $coerce)
);
}
}
sub _generate_die_prefix {
- my ($self, $prefix, $inside) = @_;
+ my ($self, $name, $prefix, $init_arg, $inside) = @_;
+
+ $self->{captures}{'$__DIE__'} ||= \ sub {
+ our ($CurrentArgument, $CurrentAttribute, $CurrentStep, $OrigSigDie);
+ $OrigSigDie ||= sub { die $_[0] };
+
+ $OrigSigDie->(
+ qq[$CurrentStep for "$CurrentAttribute"]
+ . ($CurrentArgument && ($CurrentArgument ne $CurrentAttribute)
+ ? qq[ (constructor argument: "$CurrentArgument")]
+ : "")
+ . qq[ failed: $_[0]]
+ );
+ };
+
"do {\n"
- .' my $sig_die = $SIG{__DIE__} || sub { die $_[0] };'."\n"
- .' local $SIG{__DIE__} = sub {'."\n"
- .' $sig_die->(ref($_[0]) ? $_[0] : '.perlstring($prefix).'.$_[0]);'."\n"
- .' };'."\n"
+ .' local $Method::Generate::Accessor::CurrentArgument = '
+ . B::perlstring($init_arg) . ";\n"
+ .' local $Method::Generate::Accessor::CurrentAttribute = '
+ . B::perlstring($name) . ";\n"
+ .' local $Method::Generate::Accessor::CurrentStep = '
+ . B::perlstring($prefix) . ";\n"
+ .' local $Method::Generate::Accessor::OrigSigDie = $SIG{__DIE__};'."\n"
+ .' local $SIG{__DIE__} = $__DIE__;'."\n"
.$inside
."}\n"
}
sub _generate_isa_check {
my ($self, $name, $value, $check, $init_arg) = @_;
$self->_generate_die_prefix(
- "isa check for ${\_attr_desc($name, $init_arg)} failed: ",
+ $name,
+ "isa check",
+ $init_arg,
$self->_generate_call_code($name, 'isa_check', $value, $check)
);
}
my ($self, $name, $type, $values, $sub) = @_;
$sub = \&{$sub} if blessed($sub); # coderef if blessed
if (my $quoted = quoted_from_sub($sub)) {
+ my $local = 1;
+ if ($values eq '@_' || $values eq '$_[0]') {
+ $local = 0;
+ $values = '@_';
+ }
my $code = $quoted->[1];
if (my $captures = $quoted->[2]) {
my $cap_name = qq{\$${type}_captures_for_${name}};
$self->{captures}->{$cap_name} = \$captures;
Sub::Quote::inlinify(
- $code, $values, Sub::Quote::capture_unroll($cap_name, $captures, 6), 1
+ $code, $values, Sub::Quote::capture_unroll($cap_name, $captures, 6), $local
);
} else {
- Sub::Quote::inlinify($code, $values, undef, 1);
+ Sub::Quote::inlinify($code, $values, undef, $local);
}
} else {
my $cap_name = qq{\$${type}_for_${name}};
sub _validate_codulatable {
my ($self, $setting, $value, $into, $appended) = @_;
- $appended ||= '';
my $invalid = "Invalid $setting '" . overload::StrVal($value)
- . "' for $into not a coderef $appended";
- die "$invalid or code-convertible object"
- unless ref $value and (ref $value eq 'CODE' or blessed($value));
- die "$invalid and could not be converted to a coderef: $@"
- if !eval { \&$value };
+ . "' for $into not a coderef";
+ $invalid .= " $appended" if $appended;
+
+ unless (ref $value and (ref $value eq 'CODE' or blessed($value))) {
+ die "$invalid or code-convertible object";
+ }
+
+ unless (eval { \&$value }) {
+ die "$invalid and could not be converted to a coderef: $@";
+ }
+
1;
}